[更新] 2016.07.02
的main.c
#include <stdio.h>
#include <string.h>
size_t strlen(const char *str) {
printf("%s\n", str);
return 99;
}
int main() {
const char *str = "AAA";
size_t a = strlen(str);
strlen(str);
size_t b = strlen("BBB");
return 0;
}
预期输出
AAA
AAA
BBB
使用gcc -O0 -o main main.c编译:
AAA
使用gcc -O3 -o main main.c编译
AAA
AAA
带有标志-O0
的相应asm代码000000000040057c <main>:
40057c: 55 push %rbp
40057d: 48 89 e5 mov %rsp,%rbp
400580: 48 83 ec 20 sub $0x20,%rsp
400584: 48 c7 45 e8 34 06 40 movq $0x400634,-0x18(%rbp)
40058b: 00
40058c: 48 8b 45 e8 mov -0x18(%rbp),%rax
400590: 48 89 c7 mov %rax,%rdi
400593: e8 c5 ff ff ff callq 40055d <strlen>
400598: 48 89 45 f0 mov %rax,-0x10(%rbp)
40059c: 48 c7 45 f8 03 00 00 movq $0x3,-0x8(%rbp)
4005a3: 00
4005a4: b8 00 00 00 00 mov $0x0,%eax
4005a9: c9 leaveq
4005aa: c3 retq
4005ab: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
和-O3:
0000000000400470 <main>:
400470: 48 83 ec 08 sub $0x8,%rsp
400474: bf 24 06 40 00 mov $0x400624,%edi
400479: e8 c2 ff ff ff callq 400440 <puts@plt>
40047e: bf 24 06 40 00 mov $0x400624,%edi
400483: e8 b8 ff ff ff callq 400440 <puts@plt>
400488: 31 c0 xor %eax,%eax
40048a: 48 83 c4 08 add $0x8,%rsp
40048e: c3 retq
使用标志-O0,为什么对strlen的第二次和第三次调用没有调用用户定义的strlen?
使用-O3,为什么对strlen的第三次调用已被优化?
答案 0 :(得分:1)
GCC承认strlen()
有内置内容并将其替换为内置内容。因此,您的strlen()
版本不会被调用。
我使用-fno-builtin
编译了您的代码,这会禁用内置内容,我从第一次和第三次Log in strlen
调用中获得两次strlen()
输出。可能第二个strlen()
被优化掉了,因为它的返回值没有被使用。这可能发生在之前 GCC认识到它不能使用内置strlen()
。否则,它无法优化第二次strlen()
通话,因为它具有打印消息的副作用。
同样,如果将第二次strlen()
调用的结果存储为:
size_t b = strlen(str); // call 2
然后我看,&#34;登录strlen()&#34;打印3次。
如果我使用-O3
编译(有或没有-fno-builtin
),我根本就没有输出,因为如前所述,GCC优化了整个
程序
这不是GCC的问题,因为重新定义标准函数在技术上是undefined behaviour,因此GCC可以自由处理它。
答案 1 :(得分:0)
默认情况下可能启用内置功能。如果您明智地调用用户定义函数,则更改strlen
function.So,
int strlen(const char*);
strlen_adder.c 中的
int strlen(const char *s)
同时删除#include<string.h>
文件中的main.c
。