程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> c語言頭文件中定義變量,c語言定義變量

c語言頭文件中定義變量,c語言定義變量

編輯:關於C語言

c語言頭文件中定義變量,c語言定義變量


最近在看一個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;

那麼,回到最初的問題,頭文件中確實是不可以定義變量的,而且我也沒有看到類似特殊的宏定義處理辦法,那麼這個問題他是如何處理的呢?難道在編譯階段處理?

且等下節。。。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved