在以下 C 代码中:
#include <stdio.h>
int main(void){getchar();}
它产生以下汇编:main:
push rbp
mov rbp, rsp
# no extra instruction here when header is included
call getchar
mov eax, 0
pop rbp
ret
但是,如果我不包括 stdio.h
在文件中,然后它仍然编译,但添加了看起来像随机的 mov eax, 0
操作说明:这是编译器资源管理器:https://godbolt.org/z/3fTcss .这只是“未定义行为”的一部分,还是有特殊原因导致
call getchar
之前的指令?在那里添加?
最佳答案
如果没有标题,gcc 提供了一个隐式声明 getchar
当你使用它时,就好像你之前已经声明过一样
int getchar();
(此行为由旧版本的 C 标准保证。当前版本使使用先前未声明的函数成为未定义行为,但 gcc 仍提供旧行为作为扩展。)此声明不提供有关参数类型的信息
getchar
期待。 (请记住,与 C++ 不同的是,带有 ()
的声明不会将函数声明为不带参数,而是带未指定的参数,让程序员知道函数期望什么并传递正确数量和类型的参数。)对于所有编译器都知道的,它甚至可以是可变参数,并且根据 x86-64 SysV ABI,可变参数函数期望在 al
中。用于传递参数的 vector 寄存器的数量。这里没有使用 vector 寄存器,所以编译器设置 al
至 0
在通话之前。 (实际上将 rax
全部归零会更有效,所以它会这样做。)
关于c - 如果我不包含标题,为什么在调用函数之前清除 EAX?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66572227/