为什么 (c++)*(c++) 在C++中未定义的行为
Why is (c++)*(c++) undefined behavior in C++?
我对这段代码的输出感到困惑:
int c=3;
cout<<(c++)*(c++);
我使用 gcc 并且输出是9
,但有人说这是未定义的行为,为什么?
问题是"序列点":
http://en.wikipedia.org/wiki/Sequence_point
命令式编程中的序列点定义 计算机程序的执行,保证各方 将执行先前评估的效果,并且没有侧面 后续评估的效果尚未进行。
当修改相同的变量时,序列点也会发挥作用 在单个表达式中多次出现。一个经常被引用的例子是 C 表达式 i=i++,显然两者都将 i 分配给其前一个 值和增量 i.i 的最终值是模棱两可的,因为, 根据表达式计算的顺序,增量可能会 在作业之前、之后或与作业交错发生。这 特定语言的定义可能指定一种可能 行为或简单地说行为是未定义的。在 C 和 C++ 中, 计算此类表达式会产生未定义的行为。[1]
碰巧的是,我在MSVC(Windows(和gcc(Linux(上得到了完全相同的答案 - "9"。 无论我使用 gcc("C"(还是 g++ (C++( 编译,我也会收到警告:
$ g++ -o tmp -Wall -pedantic tmp.cpp
tmp.cpp: In function "main(int, char**)":
tmp.cpp:7: warning: operation on "c" may be undefined
$ ./tmp
c=9...
未定义的行为意味着任何事情都可能发生。
输出是9
的,但使用不同的编译器或不同的编译器开关,它也可能是12
、0
或2147483647
。
C 规范留下了许多未定义的东西,它们几乎由实现该语言的人(即编写编译器(自行决定。 在这些未定义的东西中,是表达式各个部分的评估顺序。
例如,乘法是先计算后计算两个++
es,还是先计算一个++
,然后计算乘法,然后计算另一个++
?
根据编译器的编写方式、用于编译的标志、月相等,答案可能是 9、16、20,也可能产生鼻魔。始终尽量避免混淆代码和未定义的行为。查找有关如何避免这种情况的序列点。
思考序列点以及为什么您的示例同时具有unspecified behavior
和undefined behavior
的一种方法是考虑首先引入临时变量的实现:
这样的实现可以按如下方式处理帖子增量:
tmp_1=c; // read 'c'
tmp_2 = tmp_1 + 1; // calculate the incremented value
c = tmp_2; // write to 'c'
tmp_1; // the result of the expression
原始表达式(c++)*(c++)
有两个序列:
lhs_1=c; // read 'c'
lhs_2 = lhs_1 + 1; // calculate the incremented value
c = lhs_2; // write to 'c'
lhs_1; // the resulting value of the expression
rhs_1=c; // read 'c'
rhs_2 = rhs_1 + 1; // calculate the incremented value
c = rhs_2; // write to 'c'
rhs_1; // the resulting value of the expression
顺序可能是:
lhs_1=c; // read 'c'
lhs_2 = lhs_1 + 1; // calculate the incremented value
c = lhs_2; // write to 'c'
rhs_1=c; // read 'c'
rhs_2 = rhs_1 + 1; // calculate the incremented value
c = rhs_2; // write to 'c'
lhs_1 * rhs_1 // (3 * 4) new value of 'c' is 5
或:
lhs_1=c; // read 'c'
rhs_1=c; // read 'c'
lhs_2 = lhs_1 + 1; // calculate the incremented value
c = lhs_2; // write to 'c'
rhs_2 = rhs_1 + 1; // calculate the incremented value
c = rhs_2; // write to 'c'
lhs_1 * rhs_1 // (3 * 3) new value of 'c' is 4
或:
rhs_1=c; // read 'c'
rhs_2 = rhs_1 + 1; // calculate the incremented value
c = rhs_2; // write to 'c'
lhs_1=c; // read 'c'
lhs_2 = lhs_1 + 1; // calculate the incremented value
c = lhs_2; // write to 'c'
lhs_1 * rhs_1 // (4 * 3) new value of 'c' is 5
....等。
unspecified behavior
是它可以首先评估lhs或rhs。 undefined behavior
是,我们在没有中间序列点的情况下读取和写入c
。
- 编译C++时未定义的引用
- vscode g++链路故障:体系结构x86_64的未定义符号
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 未定义的引用在哪里
- 编译时的 CImg 库返回对"__imp_SetDIBitsToDevice"的未定义引用
- 对Py_Initialize()的未定义引用
- c++11评估顺序(未定义的行为)
- 使用mysql c++连接器的未定义引用
- 从python调用openMP共享库时,未定义opnMP函数
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号
- Cmake 链接问题:未定义对 Button::mousePressEvent(QGraphicsSceneMouseE
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 具有外部"c"和程序集的未定义函数
- 此增量后语句是否会导致未定义的行为?
- 尝试调用 .h 文件中定义的变量时出现变量未定义错误
- 在C++中使用内联方法时出现未定义的符号错误
- 对 Scalar ::Scalar() 的未定义引用