檔案重定義順便回想下static extern

2021-06-23 05:52:59 字數 2011 閱讀 1808

關於static,還有extern,extern平時確實用的少了點,差點都要忘了都。,。還是就說一下好了。

對於static,已經很熟了,第一是用來區域性變數的修飾,只在開始進行賦值,作用域不變但是生命週期延長,常用計數什麼的。第二對於全域性變數,沒有修飾前,是可以被其他檔案獲取的,但是如果修飾了static那麼是只能在本檔案內可見。函式當然也差不多了。 其實最常用的還是類裡的static成員用來實現常用的n多功能。

而extern用的少點,其實就是用來引用其他檔案的變數的,在其他檔案中宣告的全域性變數,只需要包含然後再這邊宣告的時候加個extern就可以了,還有一種是用於在c++中呼叫c庫函式,就需要在c++程式中用extern 「c」宣告要引用的函式。

然後就說下重定義的,一般來說我們在標頭檔案裡都不會進行各種定義,當然除了一些虛型別的簡單定義,只需要用條件編譯頭就能解決重複包含的問題,但對於編譯階段型別重定義錯誤這個方法是無法解決的,自己說的不怎麼清楚,接一下別人的說說

第一種舉個例子如果標頭檔案定義了結構,然後再test.c裡包含了包含這個標頭檔案的其他兩個檔案,預處理(見c編譯過程)後,test.c裡包含兩個struct test定義,編譯器就會報重定義錯誤。乙個巧妙辦法是套用下面標頭檔案模板(俗稱標頭檔案衛士):

#ifndef _hdrname_h //_hdrname_h按標頭檔案的檔名取名,防止同名衝突

#define _hdrname_h

…… (content of header file)

#endif

當頭檔案第一次被包含,_hdrname_h還未define,#ifndef條件滿足,預處理器進入#ifndef和#endif之間,_hdrname_h被正式define,標頭檔案內容也得到處理。當再次被包含,由於_hdrname_h已定義,開頭的#ifndef不再滿足,標頭檔案內容被直接忽略。這樣防止因標頭檔案重複包含引起的型別重定義錯誤。這種做法基本算是c的江湖標準了。

第二種情況,#ifndef能防止標頭檔案重複包含導致的編譯階段型別重定義錯誤,卻無法防止標頭檔案中的全域性變數和函式定義導致的鏈結階段實體重定義錯誤。這其實是另乙個問題,錯誤根源在於test.h裡包含變數/函式等占用記憶體的實體元素,而不僅僅是define/struct/union等虛型別。雖然用#ifndef防止test.h重複包含,但注意test1.c和test2.c中都包含test.h,預處理器會把test.h分別附到兩個原始檔開頭,相當於在test1.c和test2.c中重複定義了str1,str2兩個全域性變數。編譯完開始link時,linker會發現test1.obj和test2.obj中都有str1,str2兩個符號,於是報錯,這跟c命名衝突是同一情況。

解決辦法是在.c檔案中定義全域性變數,然後建乙個包含所有全域性變數extern宣告的標頭檔案,其他所有使用這些變數的.c檔案中都要包含這個標頭檔案。如下:

/*****main.c*****/

#include "test.h"

char str1 = "char1";

char str2 = "char2";

void main()

/***** test.h*****/

#ifndef _test_h_

#define _test_h_

extern char str1;

extern char str2;

#endif

/*****test1.c*****/

#include "test.h"

void test1()

/*****test2.c*****/

#include "test.h"

void test2()

在標頭檔案中定義函式,錯誤現象和原因類似。因此標頭檔案中可以包含型別定義和實體宣告,不應該包含實體定義。另外,有時遺漏typedef也會導致類似重定義問題:

typedef structtest_s;

如果遺漏struct前的typedef,test_s就變成無名結構體變數而不是原來的自定義型別,放在標頭檔案裡也會出錯。

最後機器還有一種方法,就是直接定義成乙個static函式,那麼包到專案裡,只有乙個標頭檔案也是沒有問題的,但是當然還是提倡良好的處理方式~~

避免標頭檔案的重定義

假設原始檔test.c中包含a.h和b.h兩個標頭檔案,而a.h和b.h裡又都包含另乙個標頭檔案x.h 很常見 那麼x.h就會被test.c兩次include,如果x.h裡定義了某結構體,如 typedef struct test 預處理 見c編譯過程 後,test.c裡包含兩個struct tes...

mac下使用karabiner重定義鍵盤

mac本很讓人不爽的就是沒有home,end,insert鍵,雖然有其他組合鍵能完成上述功能,但是仍然是不方便。特別是需要在mac下的windows虛擬機器中使用xshell之類的時候,沒有這幾個鍵是萬萬不能的。使用方法詳細介紹見官網。這裡僅給出我的配置 1.先新增私人配置 內容 version 1...

如何定義標頭檔案以防重定義的錯誤

typedef struct ortpmemoryfunctionsortpmemoryfunctions 標頭檔案被多次引用了。比如 這個是在a.h裡,main.c裡引用了a.h 和b.h,而b.h又引用了a.h,如果a.h裡沒有 ifndef a h define a h 這裡包含了typede...