What is wrong with this C cast
I came across this in an IRC channel yesterday and didn't understand why it was bad behavior:
#include <stdio.h>
int main(void)
{
char x[s开发者_C百科izeof(int)] = { '\0' }; int *y = (int *) x;
printf("%d\n", *y);
}
Is there any loss of data or anything? Can anyone give me any docs to explain further about what it does wrong?
The array x
may not be properly aligned in memory for an int
. On x86 you won't notice, but on other architectures, such as SPARC, dereferencing y
will trigger a bus error (SIGBUS) and crash your program.
This problem may occur for any address:
int main(void)
{
short a = 1;
char b = 2;
/* y not aligned */
int* y = (int *)(&b);
printf("%d\n", *y); /* SIGBUS */
}
For one thing, the array x
is not guaranteed to be aligned properly for an int
.
There's been a conversation topic about how this might affect techniques like placement new
. It should be noted that placement new needs to occur on properly aligned memory as well, but placement new is often used with memory that allocated dynamically, and allocation functions (in C and C++) are required to return memory that's suitably aligned for any type specifically so the address can be assigned to a pointer of any type.
The same isn't true for the memory allocated by the compiler for automatic variables.
Why not use a union instead?
union xy {
int y;
char x[sizeof(int)];
};
union xy xyvar = { .x = { 0 } };
...
printf("%d\n", xyvar.y);
I haven't verified it, but I would think the alignment problems mentioned by others would not be a problem here. If anyone has an argument for why this isn't portable, I'd like to hear it.
I think that while the alignment issue is true, it is not the whole story. Even if alignment is not a problem, you are still taking 4 bytes on the stack, only one of them initialized to zero, and treating them like an integer. This means that the printed value has 24 un-initialized bits. And using un-initialized values is a basic 'wrong'.
(Assuming sizeof(int)==4 for simplicity).
精彩评论