gpt4 book ai didi

c - foo(i++) + foo(i++) 在 ANSI C 中未定义吗?

转载 作者:太空狗 更新时间:2023-10-29 16:01:51 24 4
gpt4 key购买 nike

这是一个示例片段:

int i = 4,b;    
b = foo(i++) + foo(i++);

我很确定它不是未定义,因为在调用foo 之前有一个序列点。但是,如果我使用 -Wall 标志编译代码,则会生成编译器警告,提示 warning: operation on 'i' may be undefined。我意识到它说的是 may,但我只是想仔细检查一下我是否正确。

最佳答案

行为未定义。

b = foo(i++) + foo(i++);

如您所说,在第一个 i++ 的求值和对 foo 的调用之间有一个序列点,同样在第二个 i++ 的求值之间 和调用 foo。但是在 i++ 的两个求值之间,或者更具体地说,在它们的副作用(修改 i)之间没有(必然)序列点。

引用N1570 2011 ISO C 标准草案,第 6.5.2.2p10 节:

There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

第二句在这里意义重大:i++的两次求值都是“indeterminatelysequenced"相对于两个函数调用,这意味着它们可以在调用 foo 之前或之后发生。(不过,它们不是 unsequenced;它们中的每一个在调用之前或之后发生,但未指定是哪一个。)

6.5p2 说:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

将它们放在一起,符合规范的实现可以按以下顺序评估表达式:

  1. 计算第一个 i++ 并将值保存在某处。
  2. 计算第二个 i++ 并将值保存在某处。
  3. 调用 foo,将第一个保存的值作为参数传递。
  4. 调用 foo,将第二个保存的值作为参数传递。
  5. 将两个结果相加。
  6. 将总和存储在b中。

步骤 1 和步骤 2 之间没有序列点,都修改了 i,因此行为未定义。

(这实际上有点过分简化了;修改 i 的副作用可以从 i++ 的结果确定中分离出来。

底线:我们知道

b = i++ + i++;

具有未定义的行为,原因已被反复解释。在函数调用中包装 i++ 子表达式确实添加了一些序列点,但这些序列点不会将 i++ 的两个评估分开,因此不会导致行为变为定义明确。

底线:请不要写那样的代码。即使行为得到了很好的定义,证明它并确定行为应该是什么也比值得更困难。

关于c - foo(i++) + foo(i++) 在 ANSI C 中未定义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21031480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com