2016-12-28 94 views
2

我遇到,我似乎無法化解,其中有一個全局變量上聲稱在聲明中唯一的一行被重新聲明的問題。我有以下代碼:用C共享全局變量typedef定義重新聲明

test_regs.h:

#define TEST_REGS_BASE_ADDRESS  0xA0080000 

typedef struct { 
    union { 
     unsigned int data; 
     struct { 
      unsigned int RESERVED  : 16; 
      unsigned int CHAR1  : 8; 
      unsigned int CHAR0  : 8; 
     }; 
    }; 
} TEST_REG_STRUCT; 

typedef struct { 
    TEST_REG_STRUCT      TEST_REG; 
} *TEST_REGS; 

tasks.h:

#ifndef TASKS_H 
#include "test_regs.h" 

volatile TEST_REGS    TST; // This line throws an error 
volatile int     ok_global; 

void func(); 

#define TASKS_H 
#endif 

tasks.c:

#include "tasks.h" 

void func() { 
    TST->TEST_REG.CHAR1 = 0x52; 
    TST->TEST_REG.CHAR0 = 0x51; 
    ok_global++; 
} 

的main.c:

#include "tasks.h" 

main() { 
    TST = (TEST_REGS) TEST_REGS_BASE_ADDRESS; 
    ok_global = 0; 
    func(); 
} 

我試圖編譯使用以下命令上面的代碼(使用GCC的最小版本爲LEON3處理器開發):

sparc-elf-gcc -msoft-float -c -g -O2 -o test.o tasks.c main.c

即編譯嘗試產生以下錯誤:

tasks.h:4: error: conflicting types for 'TST'

tasks.h:4: error: previous declaration of 'TST' was here

值得注意的是,全局變量,ok_global不POS任何問題;只有可變的,具有In test_regs.h被聲明的類型,TST產生上述錯誤。這意味着錯誤不能歸因於標題tasks.h以某種方式被多次聲明。有沒有人有任何想法,爲什麼我寫的代碼顯然是非法的?

我會注意到,如果我擺脫所有標題,除了test_regs.h,並在一個統一的C文件中聲明,問題就消失了。另外,我真的必須有test_regs.h頭球tasks.h頭分離,test_regs.h是機器產生的,而tasks.h不是,將根據使用情況而改變。


好了,因爲這顯然不是爲主持人的頭腦鄉親下沉,這不是一個重複的問題。我可以構建我的代碼,以滿足現有崗位的建議如下(甚至在頭吸吮,test_regs.h):

tasks.h:

#ifndef TASKS_H 
#define TASKS_H 
#define TEST_REGS_BASE_ADDRESS  0xA0080000 

typedef struct { 
    union { 
     unsigned int data; 
     struct { 
      unsigned int RESERVED  : 16; 
      unsigned int CHAR1  : 8; 
      unsigned int CHAR0  : 8; 
     }; 
    }; 
} TEST_REG_STRUCT; 

typedef struct { 
    TEST_REG_STRUCT      TEST_REG; 
} *TEST_REGS; 

extern volatile TEST_REGS    TST; 
volatile int     ok_global; 

void func(); 

#endif 

tasks.c:

#include "tasks.h" 

volatile TEST_REGS TST; 

void func() { 
    TST->TEST_REG.CHAR1 = 0x52; 
    TST->TEST_REG.CHAR0 = 0x51; 
    ok_global++; 
} 

爲主。C:

#include "tasks.h" 

main() { 
    TST = (TEST_REGS) TEST_REGS_BASE_ADDRESS; 
    ok_global = 0; 
    func(); 
} 

編譯命令:

sparc-elf-gcc -msoft-float -c -g -O2 -o test.o tasks.c main.c

結果:

tasks.h:20: error: conflicting types for 'TST'

tasks.c:3: error: previous declaration of 'TST' was here

有一些具體的事情到TST是BRE全球共享;這不僅僅是一般的「我該如何分享全局變量」的問題。

+0

將'#define TASKS_H'移動到文件的頂部,緊接在'#ifndef TASKS_H'之後。 – e0k

+1

不要'typedef'指針,這是一個可怕的想法。除非它們是100%不透明類型。 –

+1

e0k,感謝您的建議,但是這並沒有解決問題。另外,我不認爲'test_regs.h'可以被多次獲取,因爲你的建議似乎暗示了,因爲'ok_global'不會出現同樣的重新聲明錯誤。 – user3570982

回答

3

變量TSTok_global在tasks.h中定義的。由於main.c和tasks.c都包含這個頭文件,所以這兩個模塊都定義了這些變量。當這些模塊被連接在一起時,你會得到多個定義的錯誤。

全局變量應該是定義爲在一個.c文件中。任何需要引用它的.c文件都應該包含一個頭文件,該頭文件具有此全局的聲明。一個聲明說「這個變量存在於某個地方」,但並沒有確切地說出在哪裏。

在tasks.h,你聲明變量是這樣的:

extern volatile TEST_REGS    TST; 
extern volatile int     ok_global; 
void func(); 

然後你在tasks.c定義它們:

#include "tasks.h" 

volatile TEST_REGS    TST; 
volatile int     ok_global; 

void func() { 
    TST->TEST_REG.CHAR1 = 0x52; 
    TST->TEST_REG.CHAR0 = 0x51; 
    ok_global++; 
} 

注意,你已經與func這樣做功能。區別在於變量聲明需要關鍵字extern,而函數聲明不需要。

+0

但是,如果你想要一致性,你也可以聲明函數'extern'。這對他們來說恰恰是多餘的。 –

+0

恭敬地說,那不是什麼事情。忽略了包含'tasks.h'頭文件的宏定義以排除多個聲明,並且忽略了'ok_global'編譯沒有錯誤的事實。這個問題是特定於'TST'的。另外,當我用'extern'在'tasks.h'中聲明'TST',然後在'tasks.c'中聲明'extern'時,我仍然得到'previous declaration'錯誤;它只是表示前面的聲明是在'tasks.c'而不是'tasks.h'中。 – user3570982

+0

@ user3570982宏守衛針對給定源模塊中多次包含的給定標題進行辯護,但它不會針對多個源模塊(包括該標題)進行防禦,並且該標題包含像您一樣的定義。至於'ok_global',鏈接器可能只捕獲重複變量的第一個實例。嘗試上述更改並查看它是如何工作的。 – dbush