-
18-09-2019 - |
题
是对以下转换安全?
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
选项编译,即使给予任何警告。
解决方案
这整个事情具有作为合法的一个且仅一个原因的机会:在2D阵列int
对象被重新解释为char
对象的数组。而在一般情况下,存储器的重新解释导致未定义的行为,语言规范明确允许重新解释“[符号/无符号] char数组”为任何类型的对象。
然而,一个正式的安全问题依然存在。语言不保证任何位模式是char
类型的有效价值。您试图通读char
类型内存的再认识理论上可以导致不确定的行为,如果它遇到陷阱表示为char
。为了安全起见在这里你必须使用unsigned char
类型,这是没有陷阱表示唯一的类型。当然,随着捕集char
的平台可以安全地被称为“外来的”。
同时,您sizeof(a + 1)
似乎没有任何意义。 a + 1
是int *
类型的表达式。为什么你要使用的指针大小在这种情况下,以增加你的x
值我不清楚。什么是你想达到什么目的?
至于没有警告......我不希望编译器在这里发出任何警告。 GCC经常发出警告类型双关(又名记忆重新解释),但由于char
重新解释明确允许(正如我上面说的),这里有没有警告。此外,显式转换通常倾向于抑制任何警告,因为他们告诉编译器的方式,你真正想要做一些事情,无论多么错误和/或危险的可能是。
其他提示
任何指针类型为char *的铸造明确由C语言允许的。所以大多数的,这是好的。
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])
或x += sizeof(b[0])
,但由于代码实际上做了什么的目的,没有人注意到这个错误。