Sne*_*ish 20 c undefined-behavior
我最近发现了一篇帖子cout << c ++ << c ;?的正确答案是什么?并且想知道是否输出
int c = 0;
printf ("%d %d", c++, c);
Run Code Online (Sandbox Code Playgroud)
还未定义?
我已经在讲座中研究了修复后和前缀运算符只有在得到分号后才增加值.所以据我说,输出0 0是正确的!
Joh*_*ode 19
我已经在讲座中研究了修复后和前缀运算符只有在得到分号后才增加值.
把你的讲师送给我,这样我就可以拿棒球棒礼貌地指出他的错误.
恰好当前或后缀的副作用++和--施加是未指定的,除了要求其下一个序列点之前发生.在表达式中
x = a++ * b
Run Code Online (Sandbox Code Playgroud)
a可以a++在评估之后立即更新,或者可以推迟更新直到a++ * b评估并将结果分配给x或之间的任何地方.
这就是为什么表达喜欢i++ * i++和printf("%d %d", c++, c)和a[i++] = i其他人都是糟糕的juju.您将根据编译器,优化设置,周围代码等获得不同的结果.语言标准明确地将行为保留为未定义,以便编译器没有义务"做正确的事情",无论正确的事情是什么.请记住,未定义行为的定义是
3.4.3
1 使用不可移植或错误的程序结构或错误数据时的未定义行为
行为,本国际标准不对其施加任何要求
2注意可能未定义的行为包括完全忽略不可预测的结果,在转换或程序执行期间的行为记录的环境特征(有或没有发出诊断消息),终止翻译或执行(发布诊断消息).
3示例未定义行为的示例是整数流上的行为.
这是一个深思熟虑的设计决策 - 未指定这些操作的顺序的基本原理是为了实现自由,重新安排评估顺序以进行优化.但是,为了换取这种自由,某些操作不会有明确的结果.
请注意,编译器可以自由尝试检测这些情况并发出诊断信息; printf("%d %d", c++, c);很容易捕获,但这将是一般情况下检测的bugger.想象一下,如果这是写的printf("%d %d", (*p)++, c); 如果p指向c,那么行为是未定义的,否则它没关系.如果p在不同的翻译单元中分配,那么在编译时无法知道这是否是一个问题.
这个概念并不难理解,但它是最一贯误解的一个(误教)的C语言方面.毫无疑问,这就是Java和C#语言规范强制对所有内容执行特定评估顺序的原因(所有操作数从左到右进行评估,并立即应用所有副作用).