2

这段代码有一个有趣的错误:

some_struct struct_array1[10] = {0};
some_struct struct_array2[10] = {0}
int i;

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     struct_array1[i].value = struct_array2[i++].value = 1)
    ;

对于大多数编译器,上述代码导致将相应数组中所有结构的“值”字段设置为 1。但是,对于一个特定的编译器(我们称之为 xcc),struct_array1 中的结构未正确初始化。所有结构的“值”字段都设置为 0,这让我很惊讶。

以下代码片段在所有编译器上都按预期工作:

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     i++)
{
    struct_array1[i].value = struct_array2[i].value = 1;
}

现在,我完全离开这里了吗,还是有问题的编译器“xcc”只是显示了一个错误?

我在第一个代码片段中找不到任何显示特定于实现的行为的东西;据我了解,后缀递增应该优先于分配,并且分配应该从右到左进行评估。第一个代码片段应该没有什么奇怪的,除了它有点不可读。

4

3 回答 3

8

您调用了未定义的行为,因为它会修改i并获取其值以用于计算新值以外的目的,而无需干预序列点。

C99 标准的相关部分是第 6.5 节中的这一条款:

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。

于 2010-03-03T12:01:27.983 回答
5

struct_array1[i].value = struct_array2[i++].value = 1

我认为这是未定义的行为,因为i++在到达下一个序列点之前不能保证完成所有副作用。下一个序列点是;语句末尾的“虚构”。这是一个常见的陷阱,我认为您可以在 SO 上找到许多与之相关的主题,只需搜索序列点即可。

于 2010-03-03T11:57:00.927 回答
0

实际上,我们不应该对同一个变量执行多个评估,在signle

表达 。如果我们这样做,那将是未定义的行为。

于 2010-03-03T12:02:03.450 回答