码迷,mamicode.com
首页 > 编程语言 > 详细

c语言头文件中定义变量

时间:2015-08-05 21:56:12      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:

最近在看一个PHP的扩展源码,编译的时候的遇到一个问题:

ld: 1 duplicate symbol for architecture x86_64

仔细看了一下源码,发现在头文件中 出现了全局变量的定义

ZEND_DECLARE_MODULE_GLOBALS(xx)

简单开来,可以这么理解

// t1.h
#ifndef T1_H
#define T1_H

int a = 0;

#endif
//------------------

//t1.c
#include "t1.h"
#include "t2.h"

int main(){
    return 0;
}
//-----------------

//t2.h
#include "t1.h"
//empty
//----------------

//t2.c
#include "t2.h"
//empty
//-------

那么第一个问题,#ifndef 的这个宏 是否应该防止了 多重定义?

答案:是。但是是在单个编译单元中(wiki translation unit)。

我们知道,一个完整的编译的过程是经过 

one.c  -->  PREPROCESSOR ->   tmp.c(temporary)   ->  COMPILER  ->  one.obj   -> LINKER ->  one.exe 

这三个过程的,而在预编译阶段,便会把include的文件展开,我们使用cc -E 命令来查看t1.c的预编译的结果:

?  t  cc -E t1.c      
# 1 "t1.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 321 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "t1.c" 2

# 1 "./t1.h" 1

int a = 0;
# 3 "t1.c" 2
# 1 "./t2.h" 1
# 4 "t1.c" 2

int main(void){
 return 0;
}

看到编译器把 t1.h 做了展开,我们看到了 a的定义。

而在t2.c 的预编译结果里,我们同样看到了a的展开定义:

?  t  cc -E t2.c  
# 1 "t2.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 321 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "t2.c" 2
# 1 "./t2.h" 1
# 1 "./t1.h" 1

int a = 0;
# 2 "./t2.h" 2
# 2 "t2.c" 2

那么,为神马 #ifdef ( include guards )没有起到 防止重定义的作用呢?

原因在于 include guards 只在同一个编译单元(一个c文件和include的文件的编译过程)内起作用,两个编译单元是编译过程是分开的,所以无法察觉到另外一个里面的#ifdefine内容

t1.c -> t1.s -> t2.o
                                                       *-> - t.otu
                           /
t2.c -> t2.s -> t2.o

所以,在头文件中是不应该define 变量,只应该declare。

那么如果我偏要呢?

如果是函数,有人给出这么个办法,添加inline或者static 关键字。或者有人直接这么搞:

#ifdef DEFINE_GLOBALS
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN int global1;
EXTERN int global2;

那么,回到最初的问题,头文件中确实是不可以定义变量的,而且我也没有看到类似特殊的宏定义处理办法,那么这个问题他是如何处理的呢?难道在编译阶段处理?

且等下节。。。

c语言头文件中定义变量

标签:

原文地址:http://www.cnblogs.com/Sorean/p/4705783.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!