当我们可以使用'extern'标识符时,为什么我们需要C中的头文件?

cs7cruho  于 2023-04-05  发布在  其他
关注(0)|答案(2)|浏览(176)

我的理解是,当链接时,如果符号是用'extern'关键字声明的,那么编译器就不会抱怨没有它的定义。此外,链接器也不会有任何问题,因为它首先会创建符号表,然后会检测到正确的源代码并填充其定义。
当构建一个由多个文件组成的没有头文件的程序时,似乎没有任何问题--如果一个文件中没有的所有符号都用“外部”声明好的话。
如果其他文件的符号识别可以用'extern'关键字检测到,那么为什么会有'头'文件?

xdnvmnnf

xdnvmnnf1#

我的理解是,当链接时,如果符号是用'extern'关键字声明的,那么编译器就不会抱怨没有它的定义。
C中的extern关键字告诉编译器它所在的声明描述了标识符,但没有定义它们。1这是编译时的效果,而不是链接时发生的情况。
如果其他文件的符号识别可以用'extern'关键字检测到,那么为什么会有'头'文件?
将声明放在头文件中允许我们将它们包含在多个源文件中,而无需重新键入或复制和粘贴它们。这避免了键入错误,并有助于确保在整个程序中对标识符使用相同的声明。此外,将声明标识符的头文件包含在定义它们的源文件中是一个很好的做法。这样编译器就可以在同一个编译中看到声明和定义,如果它们不一致,就会发出警告。
另一个原因是头文件被认为是由相关源文件的作者发布的东西(s)告诉其他程序员源文件提供了什么。在程序员可以在自己的源文件中用extern编写自己的声明之前,必须有人告诉他们这些声明是什么。编写源文件NiftyLibrary. c的人可以(并且应该)写一个手册列出所有函数的声明(以及这些函数做什么),然后任何使用NiftyLibrary. c的人都可以阅读手册并将必要的声明输入到他们的程序中。但是如果库作者提供NiftyLibrary. h,其他程序员只包括头文件而不重新输入所有内容,那么就更容易了。

脚注

1这是extern的函数之一。由于C语言的发展历史,完整的语义是复杂的。

qpgpyjmq

qpgpyjmq2#

函数原型是在C标准中定义的,所以不用从标准头文件中获取,在使用前可以直接写在源代码中。相反,头文件也定义了结构,类型和宏,这些结构,类型和宏可能因系统而异,或者取决于编译器或库配置。对于这些,标准头文件是唯一可靠的来源。
例如,经典的程序hello.c可以在不包含任何标准头的情况下以可移植的方式编写:

extern int printf(const char *format, ...);

int main(void) {
    printf("Hello world!\n");
    return 0;
}

当然,原型必须与实际实现兼容,否则即使编译没有任何错误,在运行程序时也会出现未定义的行为。兼容的原型是:

extern int printf(const char format[], ...);

但是将printf定义为extern int printf(const char *format);是不正确的,即使你从来没有用一个以上的字符串参数调用这个函数。
相反,如果你想打开一个带有fopen的文件,FILE的定义必须来自<stdio.h>。同样,如果没有至少一个定义size_t类型的头文件,malloc不能被声明。

相关问题