工程師應知道的0x10個問題(6): Static的用法

MuLong PuYang
6 min readFeb 27, 2022

--

英文原參考網址

A ‘C’ Test: The 0x10 Best Questions for Would-be Embedded Programmers

中文參考網址

C語言測試 應知道的0x10個基本問題

原文翻譯

6. What are the uses of the keyword static?

Static keyword的用法是什麼?

This simple question is rarely answered completely. Static has three distinct uses in C:

這個簡單的問題很少可以被回答的完整。Static有三種不同的用法

(a) A variable declared static within the body of a function maintains its value between function invocations.

(a) 在函數裡面的被宣告為static的變數會在函數呼叫之間維持它的數值

(b) A variable declared static within a module [1], (but outside the body of a function) is accessible by all functions within that module. It is not accessible by functions within any other module. That is, it is a localized global.

(b) 一個變數在一個module內被宣告為static,(但是在函數的body之外)是可以被在同一個module內的所有的函數存取的。在其他module中的函數不能存取。也就是說,這是個區域變數。

這裡原文的[1]是以下文字

[1] Translation unit for the pedagogues out there.

PS 其實這裡我覺得我對module的定義感覺有點有點模糊,根據我看下方的網站應是指檔案,所以在下方的實驗我會以檔案當作module來進行相關實作,如果有讀者覺得module有更好的解釋的話歡迎留言跟我說
C/C++ 中 static 的用法全局变量与局部变量

(c) Functions declared static within a module may only be called by other functions within that module. That is, the scope of the function is localized to the module within which it is declared.

在一個module內宣告為static的函數只可以被其他同一個module內的其他函數呼叫。也就是說,這個函數的範圍對它所宣告在的module而言是區域性的。

Most candidates get the first part correct. A reasonable number get the second part correct, while a pitiful number understand answer (c). This is a serious weakness in a candidate, since they obviously do not understand the importance and benefits of localizing the scope of both data and code.

大部分的應試者都會做對第一個部分。部分會做對第二部分。只有很少人會做對答案(c)。這是對應試者來說很嚴重的弱點,因為他們很明顯的不了解資料與程式碼區域範圍的重要性以及益處。

自我實作以及理解

注1: 以下是我的自我實作以及理解的部分,不保證正確而且很有可能描述不清楚或者是有錯誤,讀者若發現有可以更正的地方也歡迎留言告訴我注2: 以下皆簡單的使用Ubuntu 20.04虛擬機做測試,並非真實的嵌入式系統,所以Ubuntu 20.04出來的成果可能會與嵌入式系統上的有差異注2: 以下皆簡單的使用Ubuntu 20.04虛擬機做測試,並非真實的嵌入式系統,所以Ubuntu 20.04出來的成果可能會與嵌入式系統上的有差異

以下我主要會使用這邊文章C/C++ 中 static 的用法全局变量与局部变量對static三種用法的分類來實作

(一) 在修飾變數的時候,static 修飾的靜態區域變數只執行初始化一次,而且延長了區域變數的生命週期,直到程式運行結束以後才釋放。

這裡我們宣告了一個函數 func() 函數,在這個函數中,我們用static宣告了一個int a為0,並在下一行+1,我們呼叫了這個函數兩次,由於我們是使用static 宣告,最後的輸出結果會是2

輸出結果

1
2

(二) static 修飾全域變數的時候,這個全域變數只能在本檔中訪問,不能在其它檔中訪問,即便是 extern 外部聲明也不可以。

參考資料

The static keyword in C++

我使用上述網站的範例程式碼稍作改寫

首先我們先使用一個檔案宣告變數 num

另外我們再創立另外一個檔案將這個變數印出來

編譯檔案

gcc Embedded_system_0x10_issues_0x06_2.c Embedded_system_0x10_issues_0x06_3.c

輸出結果

20

我們可以看到輸出結果就是為20

但是如果我們將 Embedded_system_0x10_issues_0x06_2.c 的程式稍作修改,將 int num = 20 前面加上 keyword static,變成 static int num = 20

這時候我們再行編譯

gcc Embedded_system_0x10_issues_0x06_2_1.c Embedded_system_0x10_issues_0x06_3.c

就會發現出現錯誤訊息

/usr/bin/ld: /tmp/ccsqWDHO.o: in function `main':
Embedded_system_0x10_issues_0x06_3.c:(.text+0xa): undefined reference to `num'
collect2: error: ld returned 1 exit status

可以看見變數範圍被侷限在自身檔案中

(三) static 修飾一個函數,則這個函數的只能在本檔中調用,不能被其他檔調用。

參考資料

static function in CStatic functions in C

首先我們宣告一個header檔和C檔,來宣告了一個函數 func() ,並回傳數值10

接著我們再宣告一個檔案印出來這個函數的回傳值

輸出結果

10

如果我們將Embedded_system_0x10_issues_0x06_4.c改成static function

那就會得到找不到函數的結果

/usr/bin/ld: /tmp/ccNTcXus.o: in function `main':
Embedded_system_0x10_issues_0x06_5.c:(.text+0xe): undefined reference to `func'
collect2: error: ld returned 1 exit status

--

--