Reputation: 1183
I have tried to understand void*
recently by testing a few things, here is the test code:
#include <stdio.h>
int main(int argc, char** argv)
{
float nb2 = 2.2;
void* multi_type_ptr = &nb2;
printf("\nmulti_type_ptr:\n");
printf("Elem 1: %f\n",*(float*)multi_type_ptr);
// *(multi_type_ptr + 1) = 4;
// *(int*)(multi_type_ptr + 1) = 4;
*((int*)multi_type_ptr + 1) = 4;
printf("Elem 2: %d\n",*((int*)multi_type_ptr + 1));
return 0;
}
Does this instruction can't work because the language/compiler don't know how much bytes it should add to the address of multi_type_ptr
(it doesn't know the size of the type pointed by void*
)?
*(multi_type_ptr + 1) = 4;
Also a void*
cannot be dereferenced, so it should be cast to the right type, right?
This line still can't work because of the issue mentioned above.
*(int*)(multi_type_ptr + 1) = 4;
Does this assignment works because the language/compiler understand it have to add (1 * sizeof int)
to the address of multi_type_ptr
? I use cl compiler included in Visual Studio.
*((int*)multi_type_ptr + 1) = 4;
It looks like the result of (multi_type_ptr + 1)
is still an (int*)
when its content is accessed by the *
at the beginning of the line, am i right?
Thank you in advance for your future correction, explanation and reinforcement.
Upvotes: 0
Views: 55
Reputation: 98436
There are several questions here:
Does this instruction can't work because the language/compiler dont know how much bytes it should add to the adress of multi_type_ptr (it doesn't know the size of the type pointed by void*)?
*(multi_type_ptr + 1) = 4;
Yes, you are right. Some compilers (GCC for example) allow pointer arithmetic with void
pointers and treat them as if pointing to objects of size 1 (just like char*
), to avoid the frequent cast from void*
just to move around.
Does this assignment works bacause the language/compiler understand it have to add (1 * sizeof int) to the adress of multi_type_ptr? I use cl compiler included in Visual Studio.
*((int*)multi_type_ptr + 1) = 4;
Yes, right again. But note that while this code is syntactically correct, and it will compile, it is technically Undefined Behaviour for two reasons:
nb2
variable. That is you are accessing it using a different type than that defined (defined as float
, used as int
) (the exception would be that you are using char
pointers, but that is not the case).2*sizeof(int) > sizeof(float)
(quite likely) then your pointer arithmetic is taking you outside of nb2
bounds, and you are probably corrupting your stack.It looks like the result of (multi_type_ptr + 1) is still an (int*) when its content is accessed by the * at the begginning of the line, am i right?
No. Cast operator have high precedence, so this line:
*((int*)multi_type_ptr + 1) = 4;
is actually read as:
*(((int*)multi_type_ptr) + 1) = 4;
That is, like:
int *temp1 = (int*)multi_type_ptr);
int *temp2 = t1 + 1;
*temp2 = 4;
But again, beware the type aliasing!
Upvotes: 2
Reputation: 145899
*(multi_type_ptr + 1) = 4;
The expression multi_type_ptr + 1
is not valid C because C does not allow pointer arithmetic with void *
.
*((int*)multi_type_ptr + 1) = 4;
This statement compiles in your machine because (int*) multi_type_ptr + 1
does pointer arithmetic with int *
. Nevertheless pointer addition in C is undefined behavior if the resulting pointer is not in the same array object as the operand (or one past the last element) and dereferencing the resulting pointer is undefined behavior if the resulting pointer is outside the array object, so in your case the *
expression (and thus the statement) invokes undefined behavior.
Upvotes: 3