一、入题

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

#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 ;
}

② 测试结果

  程序在编译时提示:“重复定义了全局变量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 ;
}

② 测试结果

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

三、原因分析

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 ;
}

  显然,重复定义了global。

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

  program.c的预编译结果:

 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 #include <stdio.h> int main(void)
{
printf("%s\n",global);
return ;
}

  由于一开始没有定义宏__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”就可以解决重复包含引起的重复定义的问题。

头文件的宏定义#ifndef测试的更多相关文章

  1. glibc头文件和宏定义

    头文件没啥好说的,无非就是" "和< >的区别,这估计只要是学过C/C++的人都明白.现在的编译器对头文件的包含顺序没有要求,但老的C实现则不一样.当然,我们现在无需关 ...

  2. C语言的头文件和宏定义详解

    原文链接:https://blog.csdn.net/abc_12366/article/details/79155540

  3. C++头文件为什么要加#ifndef #define #endif

    #ifndef 在头文件中的作用 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时 ,就会出现大量“重定义”的错误.在头文件中实用#ifndef #de ...

  4. C 头文件、宏、编译问题

    @2019-02-15 [小记] > C 头文件的防重复包含是针对同一个源文件而言 原因: #include 头文件就是一段代码的拷贝,头文件中若有类型定义等,重复包含就会造成编译错误,若无类型 ...

  5. 头文件为什么要加#ifndef #define #endif

    #ifndef 在头文件中的作用 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时 ,就会出现大量“重定义”的错误.在头文件中实用#ifndef #de ...

  6. C++ 包含头文件 和 宏的使用 和 条件编译

    1 #define命令剖析 1.1   #define的概念     #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本. ...

  7. extern 用法,全局变量与头文件(重复定义)

    转自 https://www.cnblogs.com/chengmin/archive/2011/09/26/2192008.html 当你要引用一个全局变量的时候,你就要声明,extern int  ...

  8. [转]避免头文件重复包含以及#ifndef 与 #program once 的区别

    为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式.在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一 ...

  9. Cmake 脚本对项目输出路径和输出头文件的路径定义

    对Lib项目的统一输出路径以下时解决方案: set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Lib)set(CMAKE_LIBRARY_O ...

随机推荐

  1. mysql.cnf 配制文件详解

    代码如下: [client]port = 3306socket = /tmp/mysql.sock [mysqld]port = 3306socket = /tmp/mysql.sock basedi ...

  2. select组件

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  3. 关于ProgressBar的美化问题

    Android自带的ProgressBar其实也算不上丑陋,但是如果所有的App都使用一个模式的ProgressBar,那么估计用户就要崩溃了,打开任何一个App,擦,进度条都一模一样..有鉴于此,我 ...

  4. java_一对一自由聊天

    客户端 package cn.qianfeng.kaoti03; import java.io.BufferedReader; import java.io.IOException; import j ...

  5. <!--[if lt IE]>

    代码如下时 <!--[if lt IE9]> <script src="js/html5shiv.js"></script> <![end ...

  6. 循环json里面的数据

    {{each company as cvalue i}}   {{each value.Goods as gvalue i}}   {{each gvalue.SKU as value i}}     ...

  7. effective c++(04)之对象使用前初始化

    对于内置类型以外的初始化责任落在构造函数身上.如下: class PhoneNumber{}; class ABEntry{ public: ABEntry( const string& na ...

  8. php安全模式

    http://www.cnblogs.com/samson/archive/2011/08/08/2130550.html php安全模式:safe_mode=on|off启用safe_mode指令将 ...

  9. Virtual Studio C++ Version Macro - _MSC_VER

    MSVC++ (Visual Studio ) MSVC++ (Visual Studio ) MSVC++ (Visual Studio ) MSVC++ (Visual Studio ) MSVC ...

  10. 用变量a给出下面的定义

    a)一个整型数(An integer)b) 一个指向整型数的指针(A pointer to an integer)  c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to ...