一、入题

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

#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. FindWindowEx

    procedure CloseGameSver(); var H1, h2: HWND; begin H1 := FindWindow('TForm1', nil); h2 := FindWindow ...

  2. Centos6下yum安装MariaDB5.5(转)

    原文地址:http://www.cnblogs.com/kgdxpr/p/3209009.html vi /etc/yum.repos.d/MariaDB.repo 加入下面内容 [mariabd]n ...

  3. JSON返回的自定义

    当返回json格式的数据时,不想自己组织结果集,可以利用类的call方法. json类: <?php class Json { private $_data; public function _ ...

  4. RHCA442学习笔记-Unit11内存缓存

      Unit 11 Memory Caches 内存缓存           学习目标:                 A. 使用内存来改善运行慢的子系统的服务时间.   11.1 Strategi ...

  5. 导演类(CCDirector)

  6. ArrayList的实现原理--转

    1. ArrayList概述: ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部 ...

  7. Zookeeper简介与安装

    Zookeeper:A Distributed Coordination Service for Distributed Applications. 一.Zookeeper简介 众所周知,协同服务是分 ...

  8. Sql Server 与CLR集成

    .NET编程和SQL Server ——Sql Server 与CLR集成   一.SQL Server 为什么要与CLR集成 1. SQL Server 提供的存储过程.函数等十分有限,经常需要外部 ...

  9. java中substring和indexof() 和lastindexof()

    java中substring和indexof() 和lastindexof() str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字 ...

  10. Unity3D 之2D动画机

    这里来讲解一下2D动画机的使用 2D的时候,默认的情况下,可以调用默认的站立之类的动画,然后通过触发,可以变化自己的动画. 一:将一个图切成一些一个元素 二:创建一个精灵,给精灵添加一个动画机 三:给 ...