首页 > 代码库 > 头文件的宏定义#ifndef测试

头文件的宏定义#ifndef测试

一、入题

  在头文件的书写中,都加入了如下内容:

#ifndef __头文件名_H
#define __头文件名_H

#endif

  曾经在书中看到的解释是“防止重复定义”,今天突然想到为什么是这样的解释。

二、测试

  测试文件共三个,两个头文件:head1.h、head2.h,一个C源程序:program.c。

1、头文件没有宏定义的代码实验

① 测试代码

head1.h

unsigned char global[] = "hello world!";  

head2.h

unsigned char global[] = "hello world!"; 

program.c

#include "head1.h"
#include "head2.h"
#include <stdio.h>

int main(void)
{
    printf("%s\n",global);
    return 0;
}

② 测试结果

  程序在编译时提示:“重复定义了全局变量global”。

2、头文件含有宏定义的代码实验

① 测试代码

head1.h内容:

#ifndef __HEAD_H
#define __HEAD_H

unsigned char global[] = "hello world!"; 

#endif

head2.h

#ifndef __HEAD_H
#define __HEAD_H

unsigned char global[] = "hello world!"; 

#endif

program.c

#include "head1.h"
#include "head2.h"
#include <stdio.h>

int main(void)
{
    printf("%s\n",global);
    return 0;
}

② 测试结果

  程序正常编译、连接,生成可执行文件。

三、原因分析

1、头文件没有宏定义的代码实验

  program.c的预编译结果:

head1.h被替换为:
unsigned char global[] = "hello world!";
head2.h被替换为:
unsigned
char global[] = "hello world!"; #include <stdio.h> int main(void) { printf("%s\n",global); return 0; }

  显然,重复定义了global。

2、头文件含有宏定义的代码实验

  program.c的预编译结果:

 1 head1.h被替换为:
 2 #ifndef  __HEAD_H
 3 #define  __HEAD_H
 4 
 5 unsigned char global[] = "hello world!"; 
 6 #endif
 7 
 8 
 9 head2.h被替换为:
10 #ifndef  __HEAD_H
11 #define  __HEAD_H
12 
13 unsigned char global[] = "hello world!"; 
14 #endif
15  
16 #include <stdio.h>
17 
18 int main(void)
19 {
20     printf("%s\n",global);
21     return 0;
22 }

  由于一开始没有定义宏__HEAD_H,所以在2行的时候编译器判断为真,就定义了宏__HEAD_H和全局变量global。

  由于在3行的时候定义了宏__HEAD_H,所以编译器判断10行的条件为假,自然也会将其中的内容忽略掉。结果就是:两个头文件实际上只定义一次宏__HEAD_H和全局变量global,所以编译的时候能正常通过。

三、实际应用中

  比如STM32单片机编程的时候,main.c包含了两个外设头文件stm32f10x_gpio.h、stm32f10x_i2c.h,而这两个头文件又都包含了stm32f10x.h。在main.c的预编译过程中,显然stm32f10x.h要被包含两次。通过“头文件的宏定义#ifndef”就可以解决重复包含引起的重复定义的问题。