分析C語言static關鍵字的作用
- 分析C語言static關鍵字的作用
- 1.靜態儲存期(區域性變數使用static時)
- 2.靜態全域性變數
- 3.static與函式一起使用
- 先來看一個案例
#include <stdio.h>
int a=5;
void show_val(void)
{
int b=3;
static int c=2;
a+=5;
b+=5;
c+=5;
printf("a = %d,b = %d,c = %d\n",a,b,c);
c = b;
}
int main(void)
{
int b=0;
static int c;
a += 3;
show_val();
b += 3;
show_val ();
return 0;
}
第一次列印結果:
a = 13,b = 8,c = 7
第二次列印結果:
a = 18,b = 8,c = 13
- 為什麼會有這樣的結果呢?主要受
static
關鍵字的影響,下面就來分析static
關鍵字的作用。
1.靜態儲存期(區域性變數使用static時)
1.當static關鍵字用於函式內的區域性變數時,它改變了該變數的儲存期。通常,函式內的區域性變數具有自動儲存期,這意味著它們在進入函式時建立,在離開函式時銷燬。
2.但是,當區域性變數被宣告為
static
時,它獲得了靜態儲存期,這意味著該變數在程式開始時分配記憶體,在程式結束時釋放記憶體。
3.靜態區域性變數的初始值只會在第一次進入函式時設定,之後呼叫函式時不會再次設定。因此,靜態區域性變數可以用來跟蹤函式被呼叫的次數,或者記住跨函式呼叫之間的某些狀態。
//例如:
void Function() {
static int count = 0;
count++;
printf("Function has been called %d times\n", count);
}
// 多次呼叫 counterFunction 會顯示遞增的計數
int main()
{
for(int i = 0;i < 5,++i)
{
function();
}
return 0;
}
2.靜態全域性變數
1.全域性變數可以使用
static
關鍵字進行修飾。但是,當我們在全域性作用域(即檔案級作用域)中使用static
修飾一個變數時,它的意義與在函式內部(區域性變數)使用static
修飾變數時有所不同。2.我們知道,當在函式內部使用
static
修飾一個變數時,該變數在函式呼叫之間保持其值。這意味著它只會在第一次呼叫該函式時被初始化,並在隨後的函式呼叫中保持其值。3.當在全域性作用域中使用
static
修飾一個變數時,該變數具有內部連結。這意味著該變數只在其定義的檔案中可見,對其他檔案是不可見的。這通常用於限制全域性變數的可見性,防止其他檔案意外地訪問或修改它。因此,靜態全域性變數的特性是:
(1)它的作用域是全域性的,意味著在程式中的任何函式內部都可以訪問它(只要它們有正確的訪問許可權)。
(2)它的生命週期是整個程式的執行期間,從程式開始到程式結束。
(3)由於它是static
的,所以它的可見性被限制在定義它的檔案內部。這意味著如果你試圖在另一個原始檔中訪問這個靜態全域性變數,你將無法做到(除非使用某種特殊的連結技術,如外部宣告)。
//例如:
// file1.c
static int Val = 10;
void func()
{
printf("%d\n", Val);
}
// file2.c
//...
// 這裡不能訪問 Val,因為它在 file1.c 中是 static 的
//在這個例子中,Val 只在 file1.c 中可見,因此 file2.c 不能訪問它。
1.注意:在一個C語言工程專案中,我們往往有很多的
.c
原始檔。如果兩個或多個.c
原始檔定義了相同名字的全域性變數(即具有外部連結的變數),那麼這會導致連結器錯誤,因為連結器會在試圖將多個目標檔案合併成一個可執行檔案或庫時,發現存在名稱衝突的全域性符號。2.因為每個
.c
原始檔在編譯後都會生成一個目標檔案(比如.o
檔案),這些目標檔案包含了原始檔中的函式和全域性變數的資訊。當連結器試圖將這些目標檔案合併成一個可執行檔案時,它會查詢所有全域性符號的定義,並確保每個符號只被定義一次。因此如果兩個或多個目標檔案定義了相同的全域性變數,連結器會報告一個錯誤,指出存在重複定義的符號。因此避免在多個.c
原始檔中使用相同的變數名尤為重要,(即使全域性變數的型別不同,但只要它們的名字相同,並且都是具有外部連結的全域性變數,那麼在不同的.c
原始檔中定義它們仍然會導致連結器錯誤)。
如下是避免這種情況的方法:
(1)使用不同的變數名:這是最簡單的方法,只需確保每個
.c
檔案中的全域性變數都有唯一的名稱。(2)使用
static
關鍵字:在全域性變數的宣告前新增static
關鍵字可以將其作用域限制在單個原始檔內。這樣,即使兩個或多個原始檔都包含了相同名稱的static
全域性變數,連結器也不會報告錯誤,因為這些變數實際上是在不同的作用域中定義的。(3)使用外部變數宣告:在一個
.c
檔案中定義全域性變數,並在其他需要使用這個變數的.c
檔案中使用extern
關鍵字宣告它。這樣,所有的.c
檔案都共享同一個全域性變數的定義。(extern
關鍵字可以宣告一個函式或者一個變數的屬性是外部可連結的,意味著可以被外部檔案呼叫。)//例如: // file1.c int val = 10; // 定義全域性變數 // file2.c extern int val; // 宣告全域性變數,但不定義它 // 然後在file2.c中可以使用val
3.static與函式一起使用
當
static
與函式一起使用時,它主要有兩個主要用途:檔案作用域或內部連結。當你在一個C原始檔的檔案作用域(即在所有函式之外)中宣告一個函式為
static
時,這個函式的連結屬性會被改變為內部連結。這意味著該函式只能在宣告它的原始檔中被訪問,而不能從其他原始檔中被連結或訪問。
這有助於隱藏實現細節,使得庫的實現者可以提供某些功能,而不需要暴露這些功能的介面給庫的終端使用者。
//例如:
static void function()
{
// ......
}
// 其他原始檔不能呼叫function