Unsafe conversion
Is the following conversion safe?
int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
b[i][j]=a[i];
for(x=(char *)&b[0];x<=(char *)&a开发者_运维百科mp;b[9][9];x+=sizeof(a+1)) // Problem lies here!
printf("%d\n",*x);
I don't think the above conversion in the for
loop is safe (I think it is platform dependent). Please correct me if I am wrong. I am surprised because the code compiles without giving any warnings even when compiled using the -Wall -pedantic
options in gcc.
This whole thing has a chance of being legal for one and only one reason: the 2D int
array object is reinterpreted as an array of char
objects. While in general case memory reinterpretation leads to undefined behavior, the language specification explicitly allows "array of [signed/unsigned] char" reinterpretations for objects of any type.
However, one formal safety problem is still there. The language does not guarantee that any bit pattern is a valid value of char
type. Your attempt to read reinterpreted memory through char
type can theoretically cause undefined behavior if it encounters trap representation for char
. In order to be safe here you have to use the unsigned char
type, which is the only type that has no trap representations. Of course, a platform with a trapping char
can be safely called "exotic".
Meanwhile, your sizeof(a + 1)
doesn't seem to make any sense. a + 1
is an expression of int *
type. Why you'd want to use the pointer size to increment your x
value in this case is not clear to me. What were you trying to achieve?
As for the absence of warnings... I wouldn't expect the compiler to issue any warnings here. GCC often warns about type-punning (aka memory reinterpretation), but since char
reinterpretations are explicitly allowed (as I said above), there's no warning here. Moreover, explicit casts usually tend to suppress any warnings, since they are a way of telling the compiler that you do actually want to do something regardless of how wrong and/or dangerous it might be.
a cast of any pointer type to char* is explicitly allowed by the C language. so most of this is fine.
for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))
The first part is fine x = (char*)&b[0];
establishes a char pointer to the beginning of the array. The test is also fine x <= (char *)&b[9][9]
will be true as long as x points inside the array.
x += sizeof(a+1)
is the iffy part. On most 32 bit CPU architectures sizeof(int*) just happens to be the same as sizeof(int), so this code will probably work, but only by accident.
I'm sure what was intended was x += sizeof(a[0])
or x += sizeof(b[0])
, but since the code actually did what was intended, no-one noticed the bug.
精彩评论