请有人解释一下i = x[i]++;是否会导致未定义的行为?
注意:x[i]和i都不是易失性的,x[i]不重叠i。
这里有C11,6.5个表达式,2(重点是添加的):
如果对标量对象的副作用相对于同一标量对象上的不同副作用或使用相同标量对象值计算的值而言没有排序,则行为是未定义的。如果表达式的子表达式有多个允许的命令,则如果在任何顺序中发生这种未排序的副作用,则行为是未定义的。84)
据我所知:
没有“不同的副作用对同一个标量object"
”
是否有“多个允许订货”?
总体上:如何解释i = x[i]++;。序列点、副作用和未定义的行为(如果有的话)?
UPD。结论:i = x[i]++;可引起2种不良反应:
“操作数对象的值递增”( increment)
标准没有定义副作用发生的顺序。
因此,根据C11,4.一致性,2:
未定义行为在本国际标准中以“未定义行为”一词表示,或通过省略对行为的任何明确定义表示。
实验表明,GCC/LLVM/ICC具有顺序1-2,而MSVC (及其他一些)具有顺序2-1。
额外的(推测):为什么不使它不明确的行为?示例:“未指定行为的一个示例是副作用发生的顺序”?
发布于 2022-04-12 13:38:52
想象一下:
i = 3;
x[] = {1, 1, 1, 1, 1};因此,x[i] = 1,x[i]++ =2,x变为{1, 1, 2, 1, 1},i变为1。
为什么会有不明确的行为呢?
发布于 2022-04-12 14:39:31
如果这是真的
(在每个允许排序的子表达式中),那么您所引用的条款就不会出现特定的问题。也就是说,它的"if“的前因不成立,因此"if”(未定义的行为)的结果不会被断言。
但是,这对i和使用i值的值计算都有副作用。前者是分配的副作用,后者是x[i]++的值计算。但是,这并不是一个问题,因为对于所有形式的任务,
在左操作数和右操作数的值计算之后,对更新左操作数的存储值的副作用进行排序。
(C17 6.5.16/3)
同时,为了完整起见,
操作符的操作数的值计算是在运算符结果的值计算之前进行排序的。
(C17 6.5/1)
因此,分配对i的副作用在x[i]++的值计算之后被排序,在i的评估后被排序。
发布于 2022-04-12 13:26:38
使用同一个标量对象的值进行值计算。x[i]使用i的值。
自C11以来,赋值中存在一个序列关系。
在左操作数和右操作数的值计算之后,对更新左操作数的存储值的副作用进行排序。
(C11 6.5.16/3)
在此之前,标准讨论表达式的方式比较宽松。它没有描述关系之前的顺序。相反,我们有:
在前一个序列点和下一个序列点之间的
对象应该通过对表达式的计算来修改其存储值最多一次。此外,应只读取先验值以确定要存储的值。
您没有读取“除了确定要存储的值”以外的值,因此定义了行为。
(C99 6.5/2)
https://stackoverflow.com/questions/71843405
复制相似问题