c - 什么时候使用 include 守卫?

标签 c macros c-preprocessor header-files include-guards

我知道在头文件中使用 include guards 是为了防止某些东西被定义两次。不过,使用此代码示例完全没问题:

foo.c

#include <stdio.h>
#include <string.h>
#include "bar.h"

int main() {
    printf("%d", strlen("Test String"));
    somefunc("Some test string...");
    return 0;
}

酒吧.h

#ifndef BAR_H_INCLUDED
#define BAR_H_INCLUDED
void somefunc(char str[]);
#endif

酒吧.c

#include <stdio.h>
#include <string.h>
#include "bar.h"

void somefunc(char str[]) {
    printf("Some string length function: %d", strlen(str));
}

以上片段是用gcc -Wall foo.c bar.c -o foo编译的并且没有错误。然而,<stdio.h><string.h>被包含在没有包含守卫的情况下。当我将 bar.h 剥离为单个语句时仍然没有错误 void somefunc(char str[]); .为什么没有报错?

最佳答案

首先,include guards 的主要目的是防止某些东西在同一个翻译单元中被声明两次。 “在同一个翻译单元中”部分是这里的关键。您对两个不同翻译单元的实验与包含守卫的目的无关。它没有展示任何东西。它甚至没有远程关系。

为了利用包含防护,您必须(显式或隐式)将同一头文件两次包含到一个实现文件中。

其次,仅仅因为一些头文件没有包含保护,仅仅因为你将该头文件两次包含到同一个翻译单元中并不意味着它一定会触发错误。为了导致错误, header 必须包含特定“不可重复”类型的声明。并非每个 header 都包含此类违规声明。从这个意义上讲,并非每项声明都是冒犯性的。

你的 bar.h (如发布的那样)实际上是无害的。正式地,您不需要在 bar.h 中包含守卫.它有一个单一的函数声明,可以在一个翻译单元中重复多次。因此,多次包含此 header 不会导致错误。

但是将类似的内容添加到您的 bar.h

struct SomeStruct
{
  int i;
};

然后在同一个实现文件中两次包含它,你将以错误告终。这个错误是 include 守卫旨在防止的。该语言禁止在同一翻译单元中重复相同结构类型的完整声明。

包含保护通常无条件地放在头文件中。我敢肯定,它们存在于内部 <stdio.h><string.h>以及。目前还不清楚您为什么声称这些 header “是在没有包含保护的情况下包含的”。你检查过这些文件了吗?无论如何,您对两个不同翻译单元的实验无论如何都没有证明任何相关内容。

关于c - 什么时候使用 include 守卫?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45526830/

相关文章:

c++ - 如何用空项目启动 MFC?

c - 'variable' 的存储大小未知

c++ - 使用 Doxygen 记录发送到 MACRO C++ 的函数

c++ - 覆盖 Makefile 中的宏常量

c - #Define VS 变量

c - USART 与 ATMEGA168A -

c - 问题中信号量锁无法正常工作

macros - 使用构建宏生成构造函数调用

c++ - 计算#define的简洁方法

objective-c - 是否可以从 Objective-C 中的预处理器 DEFINE 获取本地 IP 地址?