1. 程式人生 > >[C/C++]在標頭檔案中使用static定義變數意味著什麼

[C/C++]在標頭檔案中使用static定義變數意味著什麼

宣告:本文乃轉載文章,轉載出處:https://www.cnblogs.com/computer1-2-3/p/6088388.html

看到有一位同學在標頭檔案中這麼寫:

1 static const wchar_t* g_str1 =2 static const wchar_t* g_str2 = …

這種定義變數的方式我從來沒有見過,而且它還能順利通過編譯,於是我很想知道編譯器是如何處理這種變數定義的。

定義全域性變數時使用static,意味著該變數的作用域只限於定義它的原始檔中,其它原始檔不能訪問。既然這種定義方式出現在標頭檔案中,那麼可以很自然地推測:包含了該標頭檔案的所有原始檔中都定義了這些變數,即該標頭檔案被包含了多少次,這些變數就定義了多少次。

假如將上面兩行程式碼的static去掉,編譯的時候就會出現變數重定義的錯誤,這進一步證實了上面的推測,因為沒有static的話變數的作用域是全域性的,定義了兩個以上的同名變數就會出現該錯誤。

推測終究是推測,要真正證實這個推測還要通過寫程式碼來驗證。驗證的方式是:在標頭檔案中使用static定義變數,在多個原始檔中包含該標頭檔案,然後在每個原始檔中輸出變數的地址,同時在一個原始檔中改變變數的值並輸出,在另一個原始檔中也輸出。如果每個原始檔的輸出都不同,則推測得證;否則推測是錯誤的。

下面是定義變數的標頭檔案的程式碼:

1 //Header.h
2 #pragma once
3 
4 static int
g_int = 3;

接下來在另一個頭檔案中宣告兩個測試函式:

1 //Functions.h
2 #pragma once
3 
4 void TestSource1();
5 void TestSource2();

分別在兩個原始檔中定義這兩個測試函式:

複製程式碼
 1 //Source1.cpp
 2 #include <stdio.h>
 3 #include "Header.h"
 4 
 5 void TestSource1() {
 6 
 7     wprintf(L"g_int's address in Source1.cpp: %08x\n", &g_int);
 8     g_int = 5
; 9 wprintf(L"g_int's value in Source1.cpp: %d\n", g_int); 10 }
複製程式碼複製程式碼
1 //Source2.cpp
2 #include <stdio.h>
3 #include "Header.h"
4 
5 void TestSource2() {
6 
7     wprintf(L"g_int's address in Source2.cpp: %08x\n", &g_int);
8     wprintf(L"g_int's value in Source2.cpp: %d\n", g_int);
9 }
複製程式碼

最後在main函式中呼叫這兩個測試函式:

複製程式碼
1 //Main.cpp
2 #include "Functions.h"
3 
4 int wmain() {
5 
6     TestSource1();
7     TestSource2();
8 }
複製程式碼

執行該程式:

 可以看到,雖然在程式碼中好像使用了相同的變數,但是實際上使用的是不同的變數,在每個原始檔中都有單獨的變數。所以,在標頭檔案中定義static變數會造成變數多次定義,造成記憶體空間的浪費,而且也不是真正的全域性變數。應該避免使用這種定義方式。

作為對比,下面使用正確的方式來定義全域性變數:

1 //Header.h
2 #pragma once
3 
4 extern int g_int;
複製程式碼
 1 //Source1.cpp
 2 #include <stdio.h>
 3 #include "Header.h"
 4 
 5 int g_int = 3;
 6 
 7 void TestSource1() {
 8 
 9     wprintf(L"g_int's address in Source1.cpp: %08x\n", &g_int);
10     g_int = 5;
11     wprintf(L"g_int's value in Source1.cpp: %d\n", g_int);
12 
13 }
複製程式碼

其它檔案不變。

執行程式:

 

 可以看到,這次兩個原始檔中使用的都是同一個變數。要注意的是,使用extern宣告變數時不能帶有初始值,否則仍然屬於變數定義,會出現變數重定義的錯誤。