作业评估顺序(我找到了第一个编译器错误吗?)

时间:2010-03-03 11:54:49

标签: c c99 undefined-behavior

此代码有一个有趣的错误:

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

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

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

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

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

我在第一个代码段中找不到任何显示特定于实现的行为的内容。根据我的理解,后缀增量应该优先于赋值,并且应该从右到左评估赋值。第一个代码片段应该没什么奇怪的,除了它有点不可读。

3 个答案:

答案 0 :(得分:8)

您调用了未定义的行为,因为它修改了i并且还为了计算新值以外的目的提取其值,而没有插入序列点。

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

  

在前一个和下一个序列之间   指向一个物体应该存储它   最多修改一次的值   表达的评价。   此外,先前的值应为   只读以确定要的值   存储

答案 1 :(得分:5)

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

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

答案 2 :(得分:0)

实际上,我们并不认为在同一个变量中对同一个变量进行多次评估

表达。如果我们做那件事,它将是未定义的行为。