c/c++ 中的未定义行为:i++ + ++i vs ++i + i++
Undefined behavior in c/c++: i++ + ++i vs ++i + i++
假设我们有以下代码:
int i = 1;
int j = i++ + ++i;
我知道这是一个Undefined Behavior,因为在分号之前,也就是一个序列点,i
的值已经被改变了不止一次。这意味着即使operator plus的优先级是Left-to-Right,编译器也可能有两种可能:
案例 1)
- 取
i++
的值---i
的值为1
- 取
++i
的值---i
的值为2
- 执行运算符加法并将结果 3 分配给
j
并执行 i++
的副作用(此步骤的顺序也未定义,但我们不关心,因为它不会改变结果)
案例2)
- 取
i++
的值---i
的值为1
- 做
i++
的副作用 --- i
的值为 2
- 取
++i
的值---i
的当前值为3
- 执行运算符加法并将结果 4 赋值给
j
如果这里没有问题,我有一个问题:
int j = ++i + i++;
上面的代码仍然是未定义的行为吗?
在我看来,只有一种可能:
- 做
++i
的副作用---i
的值为2
- 取
i++
的值---i
的值为2
- 执行运算符加法并将结果 4 分配给
j
并执行 i++
的副作用(此步骤的顺序也未定义,但我们不关心,因为它不会改变结果)
我说得对吗?
顺便说一句,我读过这个 link:
Undefined behavior and sequence points
int j = ++i + i++;
仍然是未定义的行为,因为 ++i
和 i++
可以在某些 CPU 中在多个管道中同时处理,这将导致不可预测的结果。
不,你错了。每个表达式 ++i
和 i++
修改 i
,因此该语句不止一次修改 i
。那是未定义的行为。
请注意,较新版本的标准不再包含 "sequence point" 的概念。
int i = 1;
int j = i++ + ++i;
计算将从右到左进行,即首先处理 ++i
,然后处理 i++
。所以 j
的值为 4.
你会得到一个警告"operation on 'i' may be undefined"但是这个表达式没有问题。
假设我们有以下代码:
int i = 1;
int j = i++ + ++i;
我知道这是一个Undefined Behavior,因为在分号之前,也就是一个序列点,i
的值已经被改变了不止一次。这意味着即使operator plus的优先级是Left-to-Right,编译器也可能有两种可能:
案例 1)
- 取
i++
的值---i
的值为1 - 取
++i
的值---i
的值为2 - 执行运算符加法并将结果 3 分配给
j
并执行i++
的副作用(此步骤的顺序也未定义,但我们不关心,因为它不会改变结果)
案例2)
- 取
i++
的值---i
的值为1 - 做
i++
的副作用 ---i
的值为 2 - 取
++i
的值---i
的当前值为3 - 执行运算符加法并将结果 4 赋值给
j
如果这里没有问题,我有一个问题:
int j = ++i + i++;
上面的代码仍然是未定义的行为吗?
在我看来,只有一种可能:
- 做
++i
的副作用---i
的值为2 - 取
i++
的值---i
的值为2 - 执行运算符加法并将结果 4 分配给
j
并执行i++
的副作用(此步骤的顺序也未定义,但我们不关心,因为它不会改变结果)
我说得对吗?
顺便说一句,我读过这个 link:
Undefined behavior and sequence points
int j = ++i + i++;
仍然是未定义的行为,因为 ++i
和 i++
可以在某些 CPU 中在多个管道中同时处理,这将导致不可预测的结果。
不,你错了。每个表达式 ++i
和 i++
修改 i
,因此该语句不止一次修改 i
。那是未定义的行为。
请注意,较新版本的标准不再包含 "sequence point" 的概念。
int i = 1;
int j = i++ + ++i;
计算将从右到左进行,即首先处理 ++i
,然后处理 i++
。所以 j
的值为 4.
你会得到一个警告"operation on 'i' may be undefined"但是这个表达式没有问题。