The as-if rule
来自cppreference.com
该页由英文版wiki使用Google Translate机器翻译而来。
该翻译可能存在错误或用词不当。鼠标停留在文本上可以看到原版本。你可以帮助我们修正错误或改进翻译。参见说明请点击这里. |
允许任何和所有的代码转换,不改变观察程序的行为
原文:
Allows any and all code transformations that do not change the observable behavior of the program
目录 |
[编辑] 解释
C + +编译器允许进行任何修改了程序,只要下面仍是如此
原文:
The C++ compiler is permitted to perform any changes to the program as long as the following remains true:
- 发生在相同的顺序写访问(读取和写入)的挥发物.原文:Accesses (reads and writes) to the volatile objects occur in the same order as written.
- 在程序终止时,写入的所有文件的数据是完全一样的,如果程序执行写入.原文:At program termination, the data written to all files is exactly as if the program was executed as written.
- 所有输入和输出操作都发生在相同的顺序和相同的内容,如果程序执行写.原文:All input and output operations occur in the same order and with the same content as if the program was executed as written.
[编辑] 注释
因为编译器(通常情况下)无法进行分析,以确定它是否或不执行I / O或挥发性访问外部库的代码,第三方库的调用,通过优化也不会受到影响。然而,标准的库调用可能被其他调用所取代,淘汰,或在优化过程中添加到程序中.
原文:
Because the compiler is (usually) unable to analyze the code of an external library to determine whether it does or does not perform I/O or volatile access, third-party library calls also aren't affected by optimization. However, standard library calls may be replaced by other calls, eliminated, or added to the program during optimization.
程序与不确定的行为,例如由于访问一个数组越界,修改const对象,求值顺序违规行为等,都是免费的作为,如果规则:他们经常更换不同的优化设置重新编译时,观察到的行为。例如,如果有符号整数溢出测试依赖于该溢出的结果,例如if(n+1 < n) abort();,it is removed entirely by some compilers因为签署溢出是不确定的行为和优化是免费的,假设它永远不会发生,检查是多余的.
原文:
Programs with undefined behavior, e.g. due to access to an array out of bounds, modification of a const object, 求值顺序 violations, etc, are free from the as-if rule: they often change observable behavior when recompiled with different optimization settings. For example, if a test for signed integer overflow relies on the result of that overflow, e.g. if(n+1 < n) abort();, it is removed entirely by some compilers because 签署溢出是不确定的行为 and the optimizer is free to assume it never happens and the test is redundant.
[编辑] 示例
int& preinc(int& n) { return ++n; } int add(int n, int m) { return n+m; } // volatile input to prevent constant folding volatile int input = 7; // volatile output to make the result a visible side-effect volatile int result; int main() { int n = input; // using built-in operators would invoke undefined behavior // int m = ++n + ++n; // but using functions makes sure the code executes as-if // the functions were not overlapped int m = add(preinc(n), preinc(n)); result = m; }
输出:
# full code of the main() function as produced by the GCC compiler # x86 (Intel) platform: movl input(%rip), %eax # eax = input leal 3(%rax,%rax), %eax # eax = 3 + eax + eax movl %eax, result(%rip) # result = eax xorl %eax, %eax # eax = 0 (the return value of main()) ret # PowerPC (IBM) platform: lwz 9,LC..1(2) li 3,0 # r3 = 0 (the return value of main()) lwz 11,0(9) # r11 = input; slwi 11,11,1 # r11 = r11 << 1; addi 0,11,3 # r0 = r11 + 3; stw 0,4(9) # result = r0; blr # Sparc (Sun) platform: sethi %hi(result), %g2 sethi %hi(input), %g1 mov 0, %o0 # o0 = 0 (the return value of main) ld [%g1+%lo(input)], %g1 # g1 = input add %g1, %g1, %g1 # g1 = g1 + g1 add %g1, 3, %g1 # g1 = 3 + g1 st %g1, [%g2+%lo(result)] # result = g1 jmp %o7+8 nop # in all cases, the side effects of preinc() were eliminated, and the # entire main() function was reduced to the equivalent of result = 2*input + 3;