转换不安全

时间:2010-02-06 02:40:34

标签: c pointers type-conversion type-safety

以下转换是否安全?

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);

我不认为for循环中的上述转换是安全的(我认为它取决于平台)。如果我错了,请纠正我。我很惊讶,因为即使使用gcc中的-Wall -pedantic选项进行编译,代码也会编译而不会发出任何警告。

2 个答案:

答案 0 :(得分:7)

这一切都有可能是合法的,只有一个原因:2D int数组对象被重新解释为char个对象的数组。虽然通常情况下内存重新解释会导致未定义的行为,但语言规范明确允许对任何类型的对象进行“[signed / unsigned] char数组”重新解释。

然而,仍存在一个正式的安全问题。该语言不保证任何位模式都是char类型的有效值。如果遇到char的陷阱表示,您尝试通过char类型读取重新解释的内存理论上会导致未定义的行为。为了安全起见,您必须使用unsigned char类型,这是唯一没有陷阱表示的类型。当然,具有陷阱char的平台可以被安全地称为“异国情调”。

与此同时,您的sizeof(a + 1)似乎没有任何意义。 a + 1int *类型的表达式。在这种情况下,为什么你想要使用指针大小增加x值,我不清楚。你想要实现什么目标?

至于没有警告......我不希望编译器在这里发出任何警告。 GCC经常警告类型惩罚(也就是内存重新解释),但是由于明确允许char重新解释(如上所述),所以这里没有警告。此外,显式强制转换通常会抑制任何警告,因为它们是告诉编译器您确实想要做某事而不管它可能有多么错误和/或危险的方式。

答案 1 :(得分:1)

C语言明确允许对char *进行任何指针类型的转换。所以大部分都很好。

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

第一部分很好x = (char*)&b[0];建立一个指向数组开头的char指针。只要x指向数组内部,测试也很正常x <= (char *)&b[9][9]将为真。

x += sizeof(a+1)是iffy的一部分。在大多数32位CPU架构中,sizeof(int *)只是发生与sizeof(int)相同,所以这段代码可能工作,但只是偶然。< / p>

我确定预期的是x += sizeof(a[0])x += sizeof(b[0]),但由于代码实际上是按预期执行的,因此没有人注意到该错误。