首页 > 代码库 > 转载 关于编译器的编译过程

转载 关于编译器的编译过程

调试的问题出现这个问题还蛮奇怪的,a.h需包含statistic.h, main.c需包含a.h和statistic.h,导致了statistic.h重复包含,hsdm_queue_ctr重复定义。
 
关于重复包含和重复定义的问题,可根据下面的分析得到认识。
 
为什么用了宏名字定义检测头文件的重复包含可还是有重复定义的错误?

我在一个头文件中定义了一个函数F, 整个头文件用:
#ifndef _XXX
#define _XXX
...
#endif
括起来以避免重复包含. 然后有两个Cpp文件都包含了这个头文件. 编译无错,链接时却显示函数F被重复定义了(在其它文件中均没有重复定义这个F). 我把其中那个报错的Cpp文件里关于这个头文件的所有内容(对它的包含,对其中函数的调用)都注释掉以后编译, 再把注释去掉重新编译链接,就又无错了.   这到底是什么道理? 该怎样使它不被重复定义?
 回复内容
【todototry】:
在一个头文件中定义了一个函数F
===============
把它放在cpp文件

【todototry】:
你放在头文件,对于使用文件而言确实未重复包含
但对整个工程而言,每个使用这个头文件的cpp文件编译生成的obj文件中均编译出了这个函数的实体,这样整个工程链接的时候,报信息

【todototry】:
所以
//name.h文件
#ifndef NAME_H
#define NAME_H

函数声明

#endif

//name.cpp文件

函数定义



【chenqiu1024】:
有点明白了. 可还不太明白, 我可能是还不懂编译器实际处理的方式:
1.  #ifndef...#define...#endif这种方式是不是仅对一个CPP文件有用,就是说可以避免一个CPP文件已经#include了一个头文件,但又#include了另一个已经#include这个头文件的头文件?
2.  为什么用了这种方法,在头文件中定义的结构体或变量不会被认为重复定义,只有函数会报错呢?

【akirya】:
重复包含是编译期间的
#ifndef...#define...#endif这个只能解决重复包含,但无法解决重复定义的
重复定义是链接期间的

【chenqiu1024】:
那是不是说, 为避免重复定义, 结构体的定义和静态数据的定义也不能放在头文件里?

【ReachZh】:
加上#pragma once 试试看

【todototry】:
结构体的定义和静态数据的定义也不能放在头文件里?
================================================
这个你这么理解即可:
你办定义可以呢看成两种:类型定义,数据定义
类型定义不分配内存的,比如类的定义,结构体的定义,它是定义一个数据类型而已
数据定义分配内存,比如类对象定义,变量定义
一个原则:
不分配内存的,放在头文件
分配内存的放在cpp文件,放置重复定义
综上所述,你就可以知道结构体的定义属于类型定义放在头文件,静态数据的定义属于数据定义放在cpp文件
对于函数相同,函数声明你可以看作类型定义,函数实现看作数据定义

【chenqiu1024】:
嗯,二位这么一说我看很清楚了, 多谢多谢

【jixingzhong】:
两个cpp文件:

A.cpp: include<?.h>  //定义了函数F
B.cpp: include<?.h>  //定义了函数F

重复定义。

因为两个 cpp 是相对独立的,
A 包含 h 文件和 B 包含h文件没有关系,
也就是 #ifndef...#define...#endi 并没有起到效果 ...

如果是 A 包含B, B包含了 h , 那么可能会起到效果...

【jixingzhong】:
一般 h 中都是声明,不是定义, 包括数据类型的声明以及函数原型的声明。

对于函数,
然后使用一个对应名字的 .cpp 文件完成函数的定义,
然后将这个 .cpp 添加到当前工程。
在其他文件调用这个函数时候,
include h 文件而不是 cpp 文件就可以了,
这样就不会重复定义了 ...