第一个问题:编译时重定义

文件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条件预处理指令为什么还会定义的更多相关文章

  1. C/C++避免头文件重复包含的方法

    C/C++避免头文件重复包含的方法 1. #ifndef 2. #pragma once 3. 混合使用 在实际的编程过程中,因为会使用多个文件,所以在文件中不可避免的要引入一些头文件,这样就可能会出 ...

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

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

  3. C/C++ 防止头文件重复包含 #pragma once 与 #ifndef 的区别

    为了避免同一个头文件被多重包含/重复包含,有两种方式: 方式一: #ifndef XXX #define XXX ... ...  //声明语句 #endif  //XXX 方式二: #pragma ...

  4. cocos2d-x 扩充引擎基类功能 引起的头文件重复包含问题的分析

    c++ 头文件包含 原因的分析:   c++  头文件的循环引用是指: .h 里面的里面的头文件的相互包含的,引起的重复引用的问题.cpp 里面包含头文件是不存在重复引用的问题(因为CPP没有#ifn ...

  5. C:防止头文件重复包含

    当一个项目比较大时,往往都是分文件,这时候有可能不小心把同一个头文件 include 多次,或者头文件嵌套包含. 方法一: #ifndef __SOMEFILE_H__ #define __SOMEF ...

  6. C++防止文件重复包含

    引用自:https://blog.csdn.net/xhfight/article/details/51550446 为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifnde ...

  7. C++ 解决文件重复包含

    // 如果zzz没有定义就定义zzz,然后执行下面的代码,定义了就不执行 #if !defined(zzz) #define zzz struct PPoint { int x; int y; }; ...

  8. C++中头文件相互包含与前置声明

    一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...

  9. C语言头文件组织与包含原则

    转自:http://www.cnblogs.com/clover-toeic/p/3728026.html 说明 本文假定读者已具备基本的C编译知识. 如非特殊说明,文中“源文件”指*.c文件,“头文 ...

随机推荐

  1. Delphi 实现最近打开文件记录菜单

    unit UntOpenMenu; //download by http://wwww.NewXing.com interface uses Windows, Messages, SysUtils, ...

  2. git回退单个文件

    git原理 Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD. gi ...

  3. openSSL实现AES加密

    Openssl是很常见的C接口的库,个人觉得易用.以下是AES加密的使用备忘.如果你有一定的密码学基础,那么就很好理解.代码是从网上弄下来的(原始地址已经忘记了),然后在尝试的过程中改了一点东西.其它 ...

  4. Java学习之classpath

    要运行class文件,必须在class文件所在的目录下,那么是不是也可以通过设置系统变量来配置呢,当然有了classpath就来了 环境变量配置有两种 1.一劳永逸的 2.set 临时变量 我们用临时 ...

  5. C++——指针与引用

    1.指针本身为对象,引用只是对象的别名.故有指针的引用,没有引用的引用,没有引用的指针.指针必须指向一个实际的对象.引用也必须是实际对象的别名. 2.允许指针赋值和拷贝,指针可指向不同的对象 3.指针 ...

  6. 2.5 webpack 进阶

    配置分离 code splitting 异步加载 理解 webpack chunk webpack 调试 2.5.1 配置分离 在大型项目中,可能 webpack.config.js 会变得越来越臃肿 ...

  7. 2019牛客多校第三场J-LRU management(map+双向链表)

    LRU management 题目传送门 解题思路 用map索引对应地址,用双向链表维护序列. 代码如下 #include <bits/stdc++.h> #define INF 0x3f ...

  8. 【C++】清空一个C++栈的快速方法

    来源:https://stackoverflow.com/questions/40201711/how-can-i-clear-a-stack-in-c-efficiently/40201744 传统 ...

  9. UVA - 143 Orchard Trees (点在三角形内)

    题意: 给出三角形的三个点的坐标(浮点数),     问落在三角形内及三角形边上的整点有多少? 思路:所有点暴力判断(点的范围1-99,三角形可能是0-100,因为这个WA了一下orz) AC代码: ...

  10. Linux操作基础

    摘要 一.Linux操作系统概述 二.Linux操作系统安装 三.Linux文件系统及文件基础 四.Linux操作系统命令使用基础 五.Linux应用程序的安装与卸载基础 五.用户及进程 六.相关信息 ...