我看到了一个我试图理解的令人费解的行为......
示例代码..请忽略我返回局部变量地址的事实..
编辑:我只是以这段代码为例来了解 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 确实打印了一个地址。但第二个 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