一、入题

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

#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. java和c#md5加密不同

    java的mad5加密后为32位字符串,c#直接加密后可能不是32位,位数也不确定. 普通的写法 public static string Md5(string sourcein) { var md5 ...

  2. Installing the PHP/MongoDB extension on Mac OSX 10.8

    Installing PHP/MongoDB extension is a two steps task on OSX: Install the autoconf tool required for ...

  3. SQL Server2000企业管理器在Win7中新建表错误的解决方法

    Sql Server2000建表错误与解决方法: 在Windwos7中SQL Server 2000企业管理器在新建表时会提示错误,尝试各种方法均告无效,包括升级SP3和SP4,最终发现如下规律可以暂 ...

  4. Mysql性能优化之缓存参数优化

    数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所以,要优化 ...

  5. Windows下安装破解JIRA6.3.6

    相关工具下载地址:http://pan.baidu.com/s/1kT9xZEJ 安装环境: WindowsXP MySQL-5.5.28 JDK1.6.0_21 JIRA功能全面,界面友好,安装简单 ...

  6. 微信小程序开闸,关于入口、推广、场景的一些观察与思考

    今夜(1月9号)零点,微信小程序正式上线.在体验了很多款小程序后,我对小程序的使用场景有了更多的认识.以下是一些想法,欢迎交流. 一.小程序的"入口"在哪儿? 1.只有访问过的小程 ...

  7. Magento强大的配置系统

    Magento的配置系统就像是Magento的心脏,支撑着Magento的运行.这套配置系统掌管着几乎所有"module/model/class/template/etc".它把整 ...

  8. 使用Azure Redis Cache

    通过上一篇博客<Redis Cache 简介>我们已经简单了解了Azure Redis Cache,这里就不过多赘述了. 1.创建Redis Cache 创建Redis Cache之前,我 ...

  9. Conversion to Dalvik format failed:Unable toexecute dex: method ID not in [0, 0xffff]: 65536

    关于方法数超限,Google官方给出的方案是这样的:https://developer.android.com/intl/zh-cn/tools/building/multidex.html 我也写过 ...

  10. mysql嵌套查询

    select * from(select t.`name` `name`,count(*) count from company t group by t.`name`) aa where aa.co ...