post-increment 运算符是否保证立即 运行?
Is post-increment operator guaranteed to run instantly?
假设我有以下代码:
int i = 0;
func(i++, i++);
增量是在返回值后立即发生的?是否保证第一个参数为0,第二个参数为1?
Is it guaranteed that the first argument will be 0, and the second argument will be 1?
没有。它的未定义行为。不保证函数参数的求值顺序是从左到右或从右到左,即求值顺序未指定,因此对 i
的副作用未排序。
C11:6.5 表达式 (p2)
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 [...]
不,您的代码有误。函数参数的计算之间没有序列点,并且只有在它们被序列点分隔时才允许对同一对象产生副作用的两个操作。
您的 "run instantly" 概念在 C 中不存在。最接近的可能是顺序操作的想法,其中上述顺序点强行分隔两个语句或表达式的执行。
此代码被破坏有两个原因:
- 为了确定要存储的值以外的其他目的,在序列点之间访问变量两次是未定义的行为。函数参数的求值之间没有顺序点。这意味着任何事情都可能发生,您的程序可能会崩溃并烧毁(或者更有可能显示不正确或垃圾值)。
- 函数参数的计算顺序是未指定的行为,这意味着您无法知道将先计算哪个。
Undefined behavior and sequence points
Why are these constructs (using ++) undefined behavior?
当你写 i++
时,你要求 两个 事情发生:
- 获取
i
的值并加一
- 将结果存储回
i
现在,您必须了解的是,虽然#1 会立即发生,但 #2 不会。思考#2 的正确方法是它发生了 "sometime later"。这就是为什么我们不能说 func(i++, i++);
做什么的原因。我们无法知道 i++
中的一个是否在第二个 i++
发生之前或之后将其结果存储回 i
。
假设我有以下代码:
int i = 0;
func(i++, i++);
增量是在返回值后立即发生的?是否保证第一个参数为0,第二个参数为1?
Is it guaranteed that the first argument will be 0, and the second argument will be 1?
没有。它的未定义行为。不保证函数参数的求值顺序是从左到右或从右到左,即求值顺序未指定,因此对 i
的副作用未排序。
C11:6.5 表达式 (p2)
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 [...]
不,您的代码有误。函数参数的计算之间没有序列点,并且只有在它们被序列点分隔时才允许对同一对象产生副作用的两个操作。
您的 "run instantly" 概念在 C 中不存在。最接近的可能是顺序操作的想法,其中上述顺序点强行分隔两个语句或表达式的执行。
此代码被破坏有两个原因:
- 为了确定要存储的值以外的其他目的,在序列点之间访问变量两次是未定义的行为。函数参数的求值之间没有顺序点。这意味着任何事情都可能发生,您的程序可能会崩溃并烧毁(或者更有可能显示不正确或垃圾值)。
- 函数参数的计算顺序是未指定的行为,这意味着您无法知道将先计算哪个。
Undefined behavior and sequence points
Why are these constructs (using ++) undefined behavior?
当你写 i++
时,你要求 两个 事情发生:
- 获取
i
的值并加一 - 将结果存储回
i
现在,您必须了解的是,虽然#1 会立即发生,但 #2 不会。思考#2 的正确方法是它发生了 "sometime later"。这就是为什么我们不能说 func(i++, i++);
做什么的原因。我们无法知道 i++
中的一个是否在第二个 i++
发生之前或之后将其结果存储回 i
。