5

以下转换安全吗?

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循环中的上述转换是安全的(我认为它取决于平台)。如果我错了,请纠正我。我很惊讶,因为即使使用-Wall -pedanticgcc 中的选项编译代码,也没有给出任何警告。

4

2 回答 2

7

整件事之所以合法,原因只有一个:二维int数组对象被重新解释为char对象数组。虽然在一般情况下内存重新解释会导致未定义的行为,但语言规范明确允许对任何类型的对象进行“[有符号/无符号]字符数组”重新解释。

然而,一个正式的安全问题仍然存在。该语言不保证任何位模式都是类型的有效值charchar如果遇到char. 为了安全起见,您必须使用unsigned char类型,这是唯一没有陷阱表示的类型。当然,带有陷阱的平台char可以安全地称为“异国情调”。

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

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

于 2010-02-06T02:53:15.530 回答
1

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

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

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

x += sizeof(a+1)是不确定的部分。在大多数 32 位 CPU 架构上,sizeof(int*)恰好与 sizeof(int) 相同,所以这段代码可能会起作用,但只是偶然。

我确定预期是x += sizeof(a[0])or x += sizeof(b[0]),但是由于代码实际上做了预期的事情,所以没有人注意到这个错误。

于 2010-02-06T03:09:16.240 回答