char* p = (char*) malloc(8 * sizeof(char));
strcpy(p, "fungus");
for (int i = 0; i < strlen(p); i++) {
printf("%c", p[i]);
}
char* p2 = (char*) malloc(4 * sizeof(char));
*p2 = *(uint16_t*) p;
printf("\nPointer: %c\n", p2[1]);
So I created a char* p to store the string "fungus". To my understanding, if I typecast p to a uint16_t* and dereference it, the returned value should be the first 2 bytes pointed to by p. So, p2[1] should be "u", since "u" is the second byte in the string "fungus". However, this isn't the case when I run my program. I've also tried to print p[0] + 1, but this just outputs "g". Is there an error in my logic?
To my understanding, if I typecast p to a uint16_t* and dereference it, the returned value should be the first 2 bytes pointed to by p.
This is not correct, for at least two reasons.
One, a pointer to a char
might not have the alignment required for a uint16_t
, and then the conversion to uint16_t
is not defined by the C standard, per C 2018 6.3.2.3 7:
… If the resulting pointer is not correctly aligned70) for the referenced type, the behavior is undefined…
That will not apply in the example code in the question, since the char *
is assigned from malloc
, and malloc
always returns an address suitably aligned for any fundamental type. However, it may apply to char *
created in other ways (including by adding offsets to p
, such as attempting to convert p+1
to uint16_t *
).
Two, accessing objects defined as char
(including those created by writing char
values to memory allocated with malloc
) as if they were uint16_t
violates the aliasing rules in C 2018 6.5 7. It is possible a C implementation might reinterpret the two char
as a uint16_t
, but it is also possible that optimization by the compiler might transform the undefined behavior into something else.
*p2 = *(uint16_t*) p;
This code is an assignment to the single char *p2
, which is p2[0]
, regardless of the fact that the right-hand side may be a 16-bit value. It does not touch p2[1]
.
If *(uint16_t*) p;
does reinterpret two eight-bit bytes of the string as a uint16_t
, then it will produce some 16-bit value that is then assigned to the single char
*p2
. If char
is unsigned, this will store the low eight bits of that value as p2[0]
, leaving p2[1]
untouched. If it is signed, an implementation-defined conversion will be performed, and the result (if a trap does not occur) will be assigned to p2[0]
, again leaving p2[1]
untouched.
Then printf("\nPointer: %c\n", p2[1]);
attempts to print a value that has not been initialized, since nothing has put a value in p2[1]
.
You could try changing *p2 = *(uint16_t*) p;
to * (uint16_t *) p2 = * (uint16_t *) p;
to copy the uint16_t
whole, instead of trying to cram it into a single byte.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.