我看到了,我想了解一個令人費解的行爲......瞭解gcc的優化
示例代碼.. 請忽略這一事實,我返回一個局部變量的地址..
編輯:我只是用這個代碼作爲例子來理解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機器上運行這一點,在主第一個printf()不會打印地址..但第二次的printf不打印任何東西。它看起來像gcc以某種方式優化了數組初始化。
如果我像下面那樣更改foo(),那麼字符串會被正確打印..我知道它是一個未定義的行爲。但我只對這裏的gcc優化有興趣。
char *foo() {
char arr[] = "hello\n";
printf("0x%x\n", arr);
return arr;
}
在原始代碼中,foo怎麼可能返回一個地址,但是初始化被優化了?這是彙編代碼..我不熟悉x86彙編......在這兩種情況下,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:
和Foo()與額外的printf的彙編代碼..
.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
你的問題聽起來像'請忽略我假定獨角獸退出的事實,但玉米的目的是什麼?' – UmNyobe
事實上,它不打印任何東西只是意味着你是幸運的;這可能意味着'ptr [0] =='\ 0''。 –
您正在用'%x'打印一個指針。如果你的指針和'unsigned'具有不同的寬度,你又有未定義的行爲。 '%p'是'void *'指針的正確格式。 –