如果我这样写:
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;
}
答案 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问题)。