コンパイラの最適化を学びながら、Cでバージョン
To understant (nop)を使用してコードを記述します。最初の2番目に2つのコードを記述C
し、オプションを使用します。 Linux
GCC
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5.1)
not a statement
y.c
x.c
generate their compiled assembly code
gcc -S
拳コードyc
desktop:~$ cat y.c
main()
{
int i=0;
}
desktop:~$ gcc -S y.c
desktop:~$
2番目のコードxc
desktop:~$ cat x.c
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;
i <= i;
/* Bitwise Operations*/
i ^ i;
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 x.c
注意:今回はの最後の2行にx.c
コメントが付けられています。
そして、私が期待していたように。生成されたアセンブリコードに違いはありません。コマンド を比較x.s
してy.s
使用しました。diff
desktop:~$ diff x.s y.s
1c1
< .file "x.c"
---
> .file "y.c"
desktop:~$
しかし、最後にコメントを外す(または追加すると言う)と、の2行が表示されx.c
ます。
i && i;
i || i;
再度-Sオプションを指定してxcをコンパイルし、ysと比較します
desktop:~$ tail x.c
sizeof(i);
(char)i;
/* Not-Logical Operation*/
!i;
/* Logical AND , OR Operators */
i && i; // unCommented && operation
i || i; // unCommented || operation
}
desktop:~$ gcc -S x.c
desktop:~$ diff x.s y.s
1c1
< .file "x.c"
---
> .file "y.c"
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
'not a statement'
コンパイラがこの2つのステートメントを実行可能ファイルに転送する理由(逆アセンブルするobjdump
と同じコードが得られます)。この2つの表現の何が特別なのか。操作は含まれていません=
。
CPUフラグレジスタを変更(設定/リセット)しますか?いいえ!
/
ゼロ除算の障害を引き起こす可能性のある除算演算 も破棄されます。
編集:回答を追加
i || i
とi && i
表現に特別なことは何もありません。どちらもNOTASTATEMENTと同等です。GCC compiler
そして、いくつかの余分な努力で削除することができます。
これを削除するには: -o2
そして-o3
フラグは便利です:これ
が私の試してみてください!!
desktop:~$ gcc -o2 -S y.c
desktop:~$ gcc -o2 -S x.c
desktop:~$ diff x.s y.s -y
.file "x.c" | .file "y.c"
.text .text
.p2align 4,,15 <
.globl main .globl main
.type main, @function .type main, @function
main: main:
pushl %ebp pushl %ebp
movl %esp, %ebp movl %esp, %ebp
popl %ebp | subl $16, %esp
> movl $0, -4(%ebp)
> leave
RHSでの余分な行は、ファイル間の不整合が原因です。
JAVA
また、C#
コンパイラがフラグなしでこの式を破棄 するという情報を追加したいと思います。