C 多次包含头文件 #包括 #包括 int main() { printf(“你好世界”); 返回0; }

C 多次包含头文件 #包括 #包括 int main() { printf(“你好世界”); 返回0; },c,header-files,C,Header Files,当我编译它时,编译器不会因为包含stdio.h两次而给出任何警告/错误。为什么会这样?函数scanf,printf等现在不是声明和定义了两次吗 谢谢,预先否,头文件通常定义一个标志,然后使用#ifndef仅当标志未定义时才包含它们自己 打开一个并查看。通常,头文件的编写方式与下面的示例类似,以防止出现此问题: #include <stdio.h> #include <stdio.h> int main () { printf ("hello world");

当我编译它时,编译器不会因为包含
stdio.h
两次而给出任何警告/错误。为什么会这样?函数
scanf
printf
等现在不是声明和定义了两次吗


谢谢,预先

否,头文件通常定义一个标志,然后使用
#ifndef
仅当标志未定义时才包含它们自己


打开一个并查看。

通常,头文件的编写方式与下面的示例类似,以防止出现此问题:

#include <stdio.h>
#include <stdio.h>

int main ()
{
   printf ("hello world");
   return 0;
}

然后,如果包含多次,则第二个实例将跳过内容。

除了使用包含保护之外,正如所指出的,只要声明兼容,多次声明函数是没有问题的。这很好:

#ifndef MYHEADER
#define MYHEADER

...


#endif
事实上,由于每个定义也是一个声明,因此每当您“前向声明”同一文件中声明的函数时,您都会声明该函数两次

不好的是创建函数的多个外部定义;但是写得好的头文件不应该创建外部定义-只创建声明。
printf
scanf
函数的(单个)定义应该在一个对象文件中,该文件在构建程序时与您的程序链接。

另一方面,“ifndef”技巧适用于其他人使用的标题(如标准标题)

如果你需要一个“私人”项目的#ifndef,那么你做得“不对”。也就是说,您可以而且应该在项目中组织标题,这样它们就不会包含多次


这样做很有帮助的一个原因是,可以防止您认为已删除的标题再次弹出


由于您无法控制如何使用公共标头,因此此技巧对于公共标头是合理的。这个技巧对于私有头是完全没有必要的。

为了补充这个答案,这里的约定被称为。如果它是一个较新的编译器(我想也是C++的话),你也可以在文件的顶部添加关键字#pragma once。
#pragma once
是一些非标准的扩展。这不是防止多重包含的有效方法。
#pragma once
在Microsoft编译器上可以很好地实现这一目的。它是否是“优化的”,因此更可取,这是有争议的,但它肯定是“有效的”。如果您使用的是GCC,
#ifndef
是一种更好的方法。一次
#pragma
提示编译器不必再次打开头文件。一些较旧的编译器将其标记为已弃用,但现代的GCC和ICC将在没有警告的情况下接受它。真是胡说八道。在私有项目中使用标题保护可能有什么负面影响?为什么要以这种方式限制标题的使用?“这很有帮助的一个原因是,它可以防止您认为已删除的标题再次弹出。”我不知道这会发生什么。我必须清理一堆库,其中原始作者认为排除标题技巧是一个“伟大”的想法。它允许他们做的是在他们包含标题的地方马虎。也就是说,它们包含了各种各样的标题。在将这组库移植到其他体系结构的过程中,我会删除一个头,以使对它的其他调用变为活动。就像“怪胎”!您需要更好的源代码管理。考虑对违规陈述的贪婪。
int foo(int, char *);
int foo(int a, char *p);
extern int foo(int x, char y[]);