Question

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 *)&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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top