5

コンパイラの最適化を学びながら、Cでバージョン To understant (nop)を使用してコードを記述します。最初の2番目に2つのコードを記述Cし、オプションを使用します。 LinuxGCCgcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5.1)
not a statementy.cx.cgenerate their compiled assembly codegcc -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 || ii && 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#コンパイラがフラグなしでこの式を破棄 するという情報を追加したいと思います。

4

1 に答える 1

2

を使用して最適化を有効-O2にすると、余分なコードが消えるはずです。

于 2012-11-26T14:26:29.110 に答える