是"返回i ++,i,i ++;" C中的未定义行为?

时间:2017-11-13 12:20:36

标签: c language-lawyer undefined-behavior c11

如果我这样写:

i = i++, i, i++;

C语言中的未定义行为

但是,如果我这样写:

return i++, i, i++; // Is it UB?

是不确定的行为?

示例:

#include <stdio.h>

int f(int i)
{
    return i++, i, i++; // Is it UB?
}
int main() {
    int i = 1;
    i = i++, i, i++;

    i = f(i);
    printf("%d\n",i);
    return 0;
}

2 个答案:

答案 0 :(得分:12)

i = i++, i, i++;是UB,因为=的优先级高于,,因此表达式被解析为(i = i++), i, i++,其中子表达式i = i++调用UB < SUP> 1)

即使代码已写为i = (i++, i, i++);仍为UB,因为现在最右侧i++和{{之间没有序列点1}},i 1)的左操作数

但是,当您删除=部分时,会删除该不明确的行为。 i = 必须按顺序排序:

return i++, i, i++;

所以它定义明确。

来源:

1) C11 6.5 / 2

  

如果相对于不同的副作用,对标量对象的副作用未被排序   在相同的标量对象上或使用相同标量的值进行值计算   对象,行为未定义。如果有多个允许的排序   表达式的子表达式,如果这样一个未经测序的一方,则行为是不确定的   效果发生在任何排序中。

然后也是C11 6.5.16 / 3

  

更新左操作数的存储值的副作用是   在左右操作数的值计算之后排序。对操作数的评估是不合理的。

值得注意的是,关于赋值的上述文本在C11和C ++ 11之间是不同的。

答案 1 :(得分:8)

return i++, i, i++;

不,它不是未定义的行为,因为逗号运算符定义了一个将修改访问分隔为i的序列点。

因此,此代码相当于:

i++;        // The left-most subexpression
i;
return i++; // The right-most subexpression

进行比较:

i = i++, i, i++;

未定义的行为,因为,的优先级低于=,因此它等同于:

(i = i++), i, i++;

并且i = i++是未定义的行为(有关此特定情况的详情,请参阅this问题)。