c - 隐式声明如何工作

标签 c declaration

当您不包含和使用 malloc 时,我们会收到隐式声明警告。

“警告:内置函数‘malloc’的隐式声明不兼容”

此警告是由于编译器假设 malloc 定义为 int malloc(size) 而它是 void* malloc(size)

但是它是如何知道 void* malloc(size) 的呢?我们没有在头文件中包含任何内容。那么如何将它与未包含的内容进行比较。

在那之后,我的代码如何工作?它如何找到正确的 malloc 定义并使用它?

扫描函数定义是否有顺序?

最佳答案

当你调用一个从未定义过的函数 f 时,会发生像这样的隐式声明:

int f();

请注意,您仍然可以将参数传递给 f,因为它没有被声明为 int f(void);(这是为了与 K&R C 向后兼容)。

因此,编译器不会“知道”malloc 接收到一个大小参数,实际上您可以按需要传递给它,它并不关心。

因此,代码能正常工作这一事实纯属运气。在 malloc 的情况下,如果代码有效,它只是意味着整数的大小与指针的大小相同 - 不多不少 - 所以,你仍然可以调用 malloc 并将其结果分配给一个指针,因为没有任何位被修剪/丢失。

真正的功能是在编译发生后的链接阶段找到的。到这个时候,你的代码已经用错误的函数原型(prototype)编译了。当然,如果链接器无法在其路径中的任何位置找到该函数,则会报告错误并中止所有操作。

对于 malloc 和其他标准库函数,可能有内置函数来提高性能。 gcc 甚至还有一个选项可以禁用内置函数(-fno-builtin-fno-builtin-function)。来自 gcc 联机帮助页:

GCC normally generates special code to handle certain built-in functions more efficiently; for instance, calls to "alloca" may become single instructions that adjust the stack directly, and calls to "memcpy" may become inline copy loops. The resulting code is often both smaller and faster, but since the function calls no longer appear as such, you cannot set a breakpoint on those calls, nor can you change the behavior of the functions by linking with a different library. In addition, when a function is recognized as a built-in function, GCC may use information about that function to warn about problems with calls to that function, or to generate more efficient code, even if the resulting code still contains calls to that function.

因此,在 malloc 的特定情况下,这就是编译器“知道”其通常签名的方式。尝试用 gcc 编译这段代码:

int main(void) {
    char *a = malloc(12, 13, 14, 15);
    return 0;
}

您会看到它会因编译错误而中止:

test.c:3: error: too many arguments to function `malloc'

如果您使用选项 -fnobuiltin,错误消失并且警告不同:

test.c:3: warning: implicit declaration of function `malloc'

这与您每次使用以前未定义的常规函数​​时收到的警告相同,因为现在编译器忽略了他对这些函数的“了解”。此示例使用 gcc,但其他编译器也会有类似的行为。

关于c - 隐式声明如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19350120/

相关文章:

c++ - 链接二进制或共享库时,为什么必须传入我依赖的共享库?

c - 我如何在没有 IDE 的情况下找到声明/定义?

c - 结构成员声明为 ": 1 "

c - 这个声明有什么问题?

c - 具有两个相同大小的操作数的表达式的类型是什么?

c - C 中超出内存限制

c - C中的阅读空间

java - 如何处理丑陋的多重声明(非方法代码的代码折叠)

c - 函数的隐式声明?

c++ - 前向申报的目的是什么?