#include <iostream>
int main()
{
int a = 0;
std::cout << a++ << ' ' << ++a << ' ' << a++ << '\n';
}
在ideone上使用C ++ 11编译时,此代码为我提供了此输出2 3 0
。
如前所述here我知道在没有插入序列点的情况下多次修改变量的值会导致未定义的行为,但是因为C ++不会从左到右计算表达式而计算机不会随机行为,我想知道编译器如何决定在上面的例子中选择哪个子表达式的第一个,第二个和第三个。
编辑:我正在使用Microsoft Visual Studio 2013,问题是由学生提出的,我无法解释为什么我们会得到这些随机结果。
答案 0 :(得分:1)
单个编译器可能不会随机运行(尽管允许使用未定义的行为)但没有“编译器”。不同的编译器将以不同的方式处理该表达式。如果给出不同的选项,相同的编译器将以不同的方式处理它。
未定义行为的关键是避免它,而不是试图理解它。除非您确实需要对特定编译器的怪癖进行反向工程,否则尝试对未定义行为的特定实例进行二次猜测是没有意义的。
答案 1 :(得分:0)
语言有一种语法,根据终端和非终结符,解析器在分解语言句子时遵循语法结构。结果(至少在概念上)是抽象语法树,将原始程序表示为操作和操作数的节点树。到目前为止,一切都是确定性的,至少只要应用类似的解析技术。
然后,代码生成设置,为每个操作创建(虚拟)机器语句。同样,这应该是非常确定的。
最后,优化开始了,现在所有的赌注都已关闭。在目前生成的代码定义的约束内,优化算法可以决定改变现状,丢弃无用的代码,在备用分支中组合重复的代码,等等......