Mar*_*k R 5 c function-call function-declaration function-definition
与 C 相比,我更喜欢 C++,但这个简单的代码示例让我大吃一惊:
int foo() {
return 3;
}
int main() {
int x;
foo(&x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/4ov9nTzjM
没有警告,没有链接问题,但此代码仍然无效。
当一些初学者用具有这个奇怪问题的代码提出问题时,我偶然发现了这一点。有人在其他网站(非英语网站)上提出了问题,我想向他提供更好的解释为什么它可以编译(并了解一些有关 C 的知识)。如果有人需要的话,他的原始代码。
我怀疑这个sis在某种程度上与隐式函数声明有关,但我不完全确定。为什么编译器不会抱怨foo使用参数调用?
这是一个程序集:
foo:
push rbp
mov rbp, rsp
mov eax, 3
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp-4]
mov rdi, rax
mov eax, 0
call foo
mov eax, DWORD PTR [rbp-4]
leave
ret
Run Code Online (Sandbox Code Playgroud)
如您所见,x仍未初始化。
编译器应该为此程序发出一条消息
int foo() {
return 3;
}
int main() {
int x;
foo(&x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
因为函数 foo 使用参数调用,尽管其标识符列表为空。所以程序有未定义的行为。
根据C标准*6.7.6.3函数声明符(包括原型)
14 标识符列表仅声明函数参数的标识符。作为该函数定义一部分的函数声明符中的空列表指定该函数没有参数。函数声明符中的空列表不是该函数定义的一部分,指定不提供有关参数数量或类型的信息。
所以该程序无效。
您可以通过以下方式使其成为有效的程序
int foo();
int main() {
int x;
foo(&x);
return x;
}
int foo( int *p ) {
return 3;
}
Run Code Online (Sandbox Code Playgroud)
尽管编译器可以发出警告,指出p未使用该参数。
在这种情况下,函数声明而不是其定义意味着没有有关参数数量和类型的信息。
与 C++ 中的 C 声明相反
int foo();
Run Code Online (Sandbox Code Playgroud)
相当于
int foo( void );
Run Code Online (Sandbox Code Playgroud)