理解しようとしている不可解な動作が見られます...
サンプルコード..ローカル変数のアドレスを返しているという事実を無視してください..
編集: gcc の最適化動作を理解するための例として、このコードを使用しています。このサンプル コードの未定義の動作によって、gcc の最適化ロジックが変更されるとは思いません。と思われる方は、説明してください。
#include<stdio.h>
char *foo() {
char arr[] = "hello world is here..\n";
return arr;
}
int main() {
char *ptr;
ptr = foo();
printf("0x%x \n", ptr);
printf("%s", ptr);
}
これを linux/x86 マシンで実行すると、main() の最初の printf でアドレスが出力されますが、2 番目の printf では何も出力されません。gcc が何らかの形で配列の初期化を最適化したようです。
次のように foo() を変更すると、文字列が正しく出力されます。未定義の動作であることはわかっています。しかし、ここで gcc の最適化を理解することだけに興味があります。
char *foo() {
char arr[] = "hello\n";
printf("0x%x\n", arr);
return arr;
}
元のコードでは、foo がアドレスを返す可能性があるのに、初期化が最適化されていない可能性はありますか? これはアセンブリコードです..私はx86アセンブリに精通していません..2つのケースでgccは正確に何をしていますか?
.LC0:
.string "hello\n"
.text
.globl foo
.type foo, @function
foo:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
movl .LC0(%rip), %eax
movl %eax, -16(%rbp)
movzwl .LC0+4(%rip), %eax
movw %ax, -12(%rbp)
movzbl .LC0+6(%rip), %eax
movb %al, -10(%rbp)
leaq -16(%rbp), %rax
leave
ret
.LFE2:
そして追加の printf を使用した foo() のアセンブリ コード..
.LC0:
.string "hello\n"
.LC1:
.string "0x%x\n"
.text
.globl foo
.type foo, @function
foo:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
subq $16, %rsp
.LCFI2:
movl .LC0(%rip), %eax
movl %eax, -16(%rbp)
movzwl .LC0+4(%rip), %eax
movw %ax, -12(%rbp)
movzbl .LC0+6(%rip), %eax
movb %al, -10(%rbp)
leaq -16(%rbp), %rsi
movl $.LC1, %edi
movl $0, %eax
call printf
leaq -16(%rbp), %rax
leave
ret