【问题标题】:Unsafe conversion不安全的转换
【发布时间】:2011-01-13 18:48:42
【问题描述】:

以下转换安全吗?

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 选项编译,代码编译时也没有给出任何警告。

【问题讨论】:

  • 我认为这是一个错误的 b。不过我可能是错的......
  • a 有 9 个元素,您正在访问 a[9]。您还缺少一个分号。因此,您还需要两个“问题在于 cmets”:-)
  • 不过,我没有投反对票 - 这些都是小错别字。
  • 我不小心投了赞成票,然后不小心点击了向下按钮,而不是重新点击了向上按钮来撤消我的赞成票。现在系统不会让我收回我的投票了。
  • @Prasoon:在这种情况下,for 标头后面的分号错误。 printf 显然是为了成为循环的主体。

标签: c pointers type-conversion type-safety


【解决方案1】:

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

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

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

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

【讨论】:

  • @Andrey T:a + 1 是 int * type 的表达式 这就是我想要的。这是来自在线编码比赛的谜题。
  • @Prasoon:从你的周期来看,我希望有人在这里使用sizeof(int),例如sizeof(a[1]) 或sizeof(*(a + 1)) 或sizeof(*a)。至于sizeof(a + 1),我还是不明白这是什么意思。这对我来说毫无意义。
  • 我假设 sizeof(int) 和 sizeof(int *) 在该特定平台上是相同的。是的,我认为 sizeof(*a) 看起来更正确。
  • 是的,为什么写sizeof(a+1) 而不是sizeof(int *)?在我的 macbook 上,它会打印每个数字 5 次,因为 sizeof(int *) 是 sizeof(int) 的 2 倍。
  • 是的,这是我犯的一个“大”错误。感谢您提出必要的更正建议:)
【解决方案2】:

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

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

第一部分很好x = (char*)&amp;b[0]; 建立一个指向数组开头的字符指针。测试也很好x &lt;= (char *)&amp;b[9][9] 只要数组内有 x 点,就会为真。

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

我确定它的意图是 x += sizeof(a[0]) 或 x += sizeof(b[0]),但由于代码确实按照预期进行,所以没有人注意到这个错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 2011-03-15
    • 2013-01-27
    • 2020-05-02
    • 2012-10-16
    • 2018-03-15
    相关资源
    最近更新 更多