在頭文件中使用static定義變量意味着什麼

[C/C++]在頭文件中使用static定義變量意味着什麼

看到有一位同學在頭文件中這麼寫:

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

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

 

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

 

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

 

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

 

下面是定義變量的頭文件的代碼:

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

 

接下來在另一個頭文件中聲明兩個測試函數:

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

 

分別在兩個源文件中定義這兩個測試函數:

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

 

最後在main函數中調用這兩個測試函數:

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

 

運行該程序:

clip_image002[4]

 

可以看到,雖然在代碼中好像使用了相同的變量,但是實際上使用的是不同的變量,在每個源文件中都有單獨的變量。所以,在頭文件中定義static變量會造成變量多次定義,造成內存空間的浪費,而且也不是真正的全局變量。應該避免使用這種定義方式。

 

作爲對比,下面使用正確的方式來定義全局變量:

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

 

其它文件不變。

 

運行程序:

clip_image002[6]

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

發佈了59 篇原創文章 · 獲贊 27 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章