两个问题: 1、头文件重复包含 2、头文件加了ifndef条件预处理指令为什么还会定义
第一个问题:编译时重定义
文件1.h
void fun1();
struct A
{
int a
char b;
};
文件2.h
#include"1.h"
struct B
{
struct A;
int a;
};
void fun2();
文件1.cpp
#include"1.h"
#include"stdio.h"
void fun1()
{
printf("fun1 is called\n");
}
文件2.cpp
#include"2.h"
#include<stdio.h>
void fun2()
{
printf("fun2 is called\n");
}
文件main.cpp
#include<stdio.h>
#include"1.h"
#include"2.h"
void main()
{
fun1();
fun2();
}
运行结果:

这个很容易解释:
因为在main.cpp中,首先包含了1.h,这是编译器就会展开1.h,发现在其中定义了结构体类型A(并不是定义变量);接着包含2.h,编译器就会展开2.h,发现2.h的第一句是#include<1.h>,这是编译器又再一次展开1.h,由此造成了结构体A的重定义。这个问题是由于在main.cpp这个文件同时包含了1.h和2.h引起的,注意是同一个文件同时包含。但是在不同CPP文件中不存在该问题,如2.cpp中包含了1.h,main.cpp也包含了1.h,但是不会出现以上问题。这就证明了源文件是单独编译的。这个问题解决非常方便,只需要加条件预处理命令即可:
//1.h
#ifndef _a1_H
#define _a1_H
void fun1();
struct A
{
int a;
char b;
};
#endif
//2.h
#include"1.h"
#ifndef _2_H
#define _2_H
struct B
{
struct A;
int a;
};
void fun2();
#endif
//1.cpp
#include"1.h"
#include"stdio.h"
void fun1()
{
printf("fun1 is called\n");
}
//2.cpp
#include"2.h"
#include<stdio.h>
void fun2()
{
printf("fun2 is called\n");
}
//main.cpp
#include<stdio.h>
#include"1.h"
#include"2.h"
void main()
{
fun1();
fun2();
}
运行结果:

第二个问题:链接时重定义
假如现在1.h中加一句话 int a;其他不变,会出现什么情况
文件1.h
#ifndef _a1_H
#define _a1_H
void fun1();
int a;//加一句话
struct A
{
int a;
char b;
};
#endif
运行结果:

这里也出现了重定义,但是这里是链接时的重定义。分析:这里在编译时由于加了条件预处理命令,所以在编译不会报错,但是由1.cpp,2.cpp,main。cpp生成的三个1.obj,2.obj,main.obj,中都定义了a 变量,造成链接时出错。如果把int a 换成extern int a就不会出错,因为extern int a,只声明变量,不分配内存,c语言允许多次声明,但不允许多次定义,即使在一个文件中出现两个extern int a,程序也不会报错。(ps:定义的函数和变量默认都是extern的)
两个问题: 1、头文件重复包含 2、头文件加了ifndef条件预处理指令为什么还会定义的更多相关文章
- C/C++避免头文件重复包含的方法
C/C++避免头文件重复包含的方法 1. #ifndef 2. #pragma once 3. 混合使用 在实际的编程过程中,因为会使用多个文件,所以在文件中不可避免的要引入一些头文件,这样就可能会出 ...
- [转]避免头文件重复包含以及#ifndef 与 #program once 的区别
为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式.在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一 ...
- C/C++ 防止头文件重复包含 #pragma once 与 #ifndef 的区别
为了避免同一个头文件被多重包含/重复包含,有两种方式: 方式一: #ifndef XXX #define XXX ... ... //声明语句 #endif //XXX 方式二: #pragma ...
- cocos2d-x 扩充引擎基类功能 引起的头文件重复包含问题的分析
c++ 头文件包含 原因的分析: c++ 头文件的循环引用是指: .h 里面的里面的头文件的相互包含的,引起的重复引用的问题.cpp 里面包含头文件是不存在重复引用的问题(因为CPP没有#ifn ...
- C:防止头文件重复包含
当一个项目比较大时,往往都是分文件,这时候有可能不小心把同一个头文件 include 多次,或者头文件嵌套包含. 方法一: #ifndef __SOMEFILE_H__ #define __SOMEF ...
- C++防止文件重复包含
引用自:https://blog.csdn.net/xhfight/article/details/51550446 为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifnde ...
- C++ 解决文件重复包含
// 如果zzz没有定义就定义zzz,然后执行下面的代码,定义了就不执行 #if !defined(zzz) #define zzz struct PPoint { int x; int y; }; ...
- C++中头文件相互包含与前置声明
一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...
- C语言头文件组织与包含原则
转自:http://www.cnblogs.com/clover-toeic/p/3728026.html 说明 本文假定读者已具备基本的C编译知识. 如非特殊说明,文中“源文件”指*.c文件,“头文 ...
随机推荐
- WinDbg中Check for invalid symbols or bad syntax(断点设置)解决办法
基础知识 bp 程序运行过程中下断点 bu 程序未加载之前下断点 bl 列出所有断点 bc 清除断点 今天在调试驱动的时候 发现下好断点后 无法调试 WinDbg显示 kd> g Break ...
- dubbo入门学习(一)-----分布式基础理论、架构发展以及rpc、dubbo核心概念
一.分布式基础理论 1.什么是分布式系统? <分布式系统原理与范型>定义: “分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统” 分布式系统(distributed ...
- (14)centos7 进程管理
一.查询进程 1. 进程显示 ps -a 显示当前所有的进程信息 -u 以用户的格式显示进程信息 -x 显示后台进程运行的参数 ps -aux #通常查看内存 USER #执行进程的用户 PID #进 ...
- 技巧&注意事项合集
技巧&注意事项合集 杂项 OI Wiki有很多实用的东西 编程环境 打开Dev-C++中工具-编译选项-代码生成/优化-代码警告-显示最多警告信息的开关,可以检查出一堆傻逼错误 define ...
- 剑指offer——43数据流中的中位数
题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值.我们 ...
- CM 安装cdh 版本及出现问题
添加节点: 安装完cdh 后jps出现:process information unavailable 解决办法:
- 如何删除github里的项目
1.登录github网站后,就会看到如下画面,在头像下面有个你的项目资源这一栏,假如我要删除名为“hhh”的项目,现在鼠标点进这个项目里面 2.进去后点setting 点进去后,默认是选择了OPtio ...
- Quartz CronTrigger 整配置说明
Quartz cron 表达式的格式向下支持到秒级别的计划,而 UNIX cron 计划仅支持至分钟级. Quartz用cron 表达式存放执行计划,引用了cron表达式的CronTrigger在计 ...
- zdump - 时区输出器
SYNOPSIS 总览 zdump [ -v ] [ -c cutoffyear ] [ zonename ... ] 描述 Zdump 对命令行中的每一个 zonename 输出其当前时间. 提供了 ...
- java.sql.Date和java.util.Date的联系和区别
1) java.sql.Date是java.util.Date的子类,是一个包装了毫秒值的瘦包装器,允许 JDBC 将毫秒值标识为 SQL DATE 值.毫秒值表示自 1970 年 1 月 1 日 0 ...