关于c中“非法”的优化?
在学习编译器优化时,我在Linux
下使用GCC
版本gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5.1)
编写代码
为了理解C中not a statement
(nop),我先写了两个代码,然后使用gcc -S
选项generate their compiled assembly code
。
拳头代码yc
desktop:~$ cat yc main() { int i=0; } desktop:~$ gcc -S yc desktop:~$
第二个代码xc
desktop:~$ cat xc main() { int i=0; /* Loops and if*/ while(0); for(;0;); if(0); /* Arithmetic Operations */ i * i; i / i; i - i; i + i; i % i; +i; -i; /* Comparison operators */ i == i; i != i; i i; i >= i; i <= i; /* Bitwise Operations*/ i ^ i; i | i; i & i; ~i; i <> i; /* Address Operatins*/ &i; *(&i); (&i)[i]; /* Ternary conditional operation*/ i? i : i; /* Other Operations*/ sizeof(i); (char)i; /* Not-Logical Operation*/ !i; /* Logical AND , OR Operators */ // i && i; // Commented && operation // i || i; // Commented || operation } desktop:~$ gcc -S xc
注意 :此时xc
中的最后两行被注释。
正如我所期待的那样。 它们生成的汇编代码没有区别。 我使用diff
命令比较了xs
和ys
。
desktop:~$ diff xs ys 1c1 .file "yc" desktop:~$
但是当我在xc
取消最后一个(或者说添加)两xc
。
i && i; i || i;
再次使用-S选项编译xc并与ys进行比较
desktop:~$ tail xc sizeof(i); (char)i; /* Not-Logical Operation*/ !i; /* Logical AND , OR Operators */ i && i; // unCommented && operation i || i; // unCommented || operation } desktop:~$ gcc -S xc desktop:~$ diff xs ys 1c1 .file "yc" 10,21d9 < movl -4(%ebp), %eax < testl %eax, %eax < je .L3 < movl -4(%ebp), %eax < testl %eax, %eax < .L3: < movl -4(%ebp), %eax < testl %eax, %eax < jne .L8 < movl -4(%ebp), %eax < testl %eax, %eax < .L8: desktop:~$
问题 :
我只是无法理解为什么表达式i || i
i || i
和i && i
不等同于'not a statement'
?
为什么编译器将这两个语句转换为可执行文件(我们可以用objdump
反汇编获得相同的代码)。 这两个表达有什么特别之处。 他们不包括=
操作。
它们是否更改(设置/重置)CPU标志寄存器? 我觉得不是!
丢弃偶数/
除法运算,可能导致除零故障。
编辑 :添加答案
i || i
没有什么特别之处 i || i
和i && i
表达。 两者都相当于NOT A STATEMENT。 并且可以通过一些额外的努力由GCC compiler
删除。
要删除它: -o2
和-o3
标志很有用:
这是我的尝试!!
desktop:~$ gcc -o2 -S yc desktop:~$ gcc -o2 -S xc desktop:~$ diff xs ys -y .file "xc" | .file "yc" .text .text .p2align 4,,15 movl $0, -4(%ebp) > leave
RHS中的额外行是由于文件之间的错位。
我还想添加JAVA
和C#
编译器在没有任何标志的情况下丢弃此表达式的信息。
使用-O2
启用优化,您应该看到额外的代码消失。