C Language
釐清 Global / Static / Extern 變數的用法
about me
EE degree back in 1982
Z80 was the most popular CPU
Pascal/Fortran/COBOL were popular languages
Apple ][ + BASIC and CP/M
intel 80386SX PC mother board designer
......
Interested in Linux since 2016

Z80 CPU

intel 80386SX CPU
photo source: wikipedia.org

Apple ][
marconi.jiang@gmail.com
References
-
Stackoverflow : static and extern global variables in C and C++
-
Stackoverflow : Static variable inside of a function in C
-
wiki : Static variable、Global variable
-
Stackoverflow : In C,why is multiple declarations working fine for a global variable but not for a local variable?
-
伯乐在线:帮 C/C++ 程序员彻底了解链接器
-
C 語言, 關於變數的二三事:C 語言的變數有所謂的 storage class, 初學時對當中的差異並不是很容易弄清楚, 後來我把各種條件稍作整理, ...
先來看看 Stackoverflow 的例子
header.h
main.c
int varGlobal=7;#include <stdio.h>
#include <stdlib.h>
#include "header.h"
void function(int i)
{
static int a=0;
a++;
int t=i;
i=varGlobal;
varGlobal=t;
printf("Call #%d:\ni=%d\nvarGlobal=%d\nt=%d\n\n",a,i,varGlobal,t);
}
int main() {
function(4);
function(6);
function(12);
return 0;
}輸出的結果
Call #1:
i=7
varGlobal=4
t=4
Call #2:
i=4
varGlobal=6
t=6
Call #3:
i=6
varGlobal=12
t=12
- 其中的 varGlobal 就是 global 變數(雖然這例子不恰當, 因為習慣上 global 變數用大寫當開頭)
- 也就是 Call # 後的數字, 是 static 變數
好奇寶寶的我就有了許多的黑人問號❓❓❓❓❓
static int a = 0;好奇寶寶的問題
-
為什麼在原始程式 .c 檔案調用 varGlobal 時, 不需要宣告 extern, compile 也沒 warning
-
a 在 宣告時, 同時設定為 0, 重複執行 3 次, 為什麼 a 不是都從 a = 0;
-
a++; 得到一樣是 1的結果, 而只是執行 a++ 3 次, 得到 1, 2, 3 結果
header.h
int varGlobal=7;
main.c
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
void function(int i) {
static int a=0;
a++;
int t=i; i=varGlobal; varGlobal=t;
printf("Call #%d:\ni=%d\nvarGlobal=%d\nt=%d\n\n",a,i,varGlobal,t); }
int main() { function(4); function(6); function(12); return 0; }static int a = 0;
a++;Stackoverflow 另一個問題剛好有解答、wiki 也有 static 說明
-
static variable is initialised only once (unlike auto variable) and further defination of static variable would be bypassed during runtime.
-
compiler arranges that static variable initialization does not happen each time the function is entered
void foo()
{
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main()
{
foo();// x = 6
foo();// x = 7
return 0;
}* Stackoverflow : Static variable inside of a function in C * wiki : Static variables
當程式是多個檔案,才有使用宣告的必要。
-
金玉良言:當程式只有一個檔案,變數就用定義就夠了。不需要使用到變數宣告。當程式是多個檔案,才有使用宣告的必要。
-
變數與函式,使用前必須先定義,而且也只能定義這唯一的一次。
(分配儲存空間當然只能唯一的一次) -
現代習慣做法,原則為:『把宣告寫在 .h 檔,把定義寫在 .c 檔』若沒按照這個原則,在 .h 檔裡放了定義,當某 .h 檔有多個 .c 檔去 include 它,就會產生重複定義的錯誤。『可以宣告很多次,但定義必須是唯一的!』
-
不要在宣告變數時,設定初始值!
※ 在宣告變數的同時設定初始值,會轉變成定義。
編譯器行為 compiler behavior:
| 宣告變數 Declaration |
只告知 compiler 變數的存在,和告知變數的型態。 | extern int i; static char j; |
|---|---|---|
| 定義變數 Definition | 叫 compiler 為變數分配儲存空間。 (當然也得知變數的存在與型態) |
int i; int i = 2; |
整理關於 global static extern 的常用規範 - wiki 說明
-
A variable name's scope affects its extent.
Scope is an important part of the name resolution of a variable. Most languages define a specific scope for each variable (as well as any other named entity), which may differ within a given program. The scope of a variable is the portion of the program code for which the variable's name has meaning and for which the variable is said to be "visible". Entrance into that scope typically begins a variable's lifetime (as it comes into context) and exit from that scope typically ends its lifetime (as it goes out of context). For instance, a variable with "lexical scope" is meaningful only within a certain function/subroutine, or more finely within a block of expressions/statements (accordingly with function scope or block scope); this is static resolution, performable at parse-time or compile-time. Alternatively, a variable with dynamic scope is resolved at run-time, based on a global binding stack that depends on the specific control flow. Variables only accessible within a certain functions are termed "local variables". A "global variable", or one with indefinite scope, may be referred to anywhere in the program.
Extent, on the other hand, is a runtime (dynamic) aspect of a variable. Each binding of a variable to a value can have its own extent at runtime. The extent of the binding is the portion of the program's execution time during which the variable continues to refer to the same value or memory location. A running program may enter and leave a given extent many times, as in the case of a closure.
-
It is possible to put some additional constraints on the visibility of global variables. By default, a global variable will be visible everywhere, but functions files other than the one in which it is defined won't necessarily know what type it has. This latter problem can be fixed using an externdeclaration, which says that there is a variable somewhere else of a particular type that we are declaring (but not defining, so no space is allocated). In contrast, the static keyword (on a global variable) specifies that it will only be visible in the current file, even if some other file includes a declaration of a global variable of the same name
整理關於 global static extern 的常用規範 - wiki 說明 (2)
- Most variables that you will use in C are either parameters to functions or local variables inside functions. These have local scope, meaning the variable names can only be used in the function in which they are declared, and automatic extent, meaning the space for the variable is allocated, typically on the stack, when the function is called, and reclaimed when the function exits. (If the function calls itself, you get another copy of all the local variables; see recursion.)
-
On very rare occasions you might want to have a variable that survives the entire execution of a program (has static extent) or that is visible throughout the program (has global scope). C provides a mechanism for doing this that you shold never use under normal circumstances. Pretty much the only time you are going to want to have a variable with static extent is if you are keeping track of some piece of information that (a) you only need one instance of, (b) you need to survive between function calls, and (c) it would be annoying to pass around as an extra argument to any function that uses it. An example would be the internal data structures used by malloc, or the count variable in the function below:
-
a static variable is a variable that has been allocated "statically", meaning that its lifetime (or "extent") is the entire run of the program. This is in contrast to shorter-lived automatic variables, whose storage is stack allocated and deallocated on the call stack; and in contrast to objects, whose storage is dynamically allocated and deallocated in heap memory.
-
Variable lifetime is contrasted with scope (where a variable can be used): "global" and "local" refer to scope, not lifetime, but scope often implies lifetime. In many languages, global variables are always static, but in some languages they are dynamic, while local variables are generally automatic, but may be static.
In general, static memory allocation is the allocation of memory at compile time, before the associated program is executed, unlike dynamic memory allocation or automatic memory allocation where memory is allocated as required at run time.[1]
整理關於 global static extern 的常用規範 - 簡單的說
-
In modern programming languages, a variable has attributes containing a scope and an extent
-
範疇 Scope:有 Local 區域變數, Global 全域變數 兩類, a limit on where the name is meaningful, which allows the same name to be used for different variables in different parts of the program
-
全域變數(Global Variable):定義在函式之外的變數。生命週期直到程式結束,而且跨檔案共享(盡量少用)
-
區域變數(Local Variable):定義在大括號 { } 之內的變數。生命週期在大括號 { } 之間
-
-
範圍或生命週期 Extent (or life time):有 Automatic, Static 兩種, the duration of the variable's existence, controlling when the program allocates and deallocates space for it
-
Static:1.存取的範圍:只在定義的文件檔內,不具跨文件檔共享。 2.生命週期:直到程式結束,才會從記憶體消逝。
-
用 static 修飾的區域變量實際上是全域變量,因為雖然它們僅在某個函數中可見,但其生命周期存在於整個程式中。同樣,用 static 修飾的全域變量也被認為是全域的,儘管它們只能由它們所在的文件內的函數存取
-
-
C 程式執行時所有的資料變數置於記憶體的三種區域:
-
資料區 (Data segment)︰ 全域變數、static 變數、常數, 於 compile 階段指定。
-
堆疊區 (Stack)︰ 區域變數 (Auto variable), 函式參數,暫時變數, 於程式執行時運用, 儲存空間大小受限於 OS 設計。
-
Heap 區︰ 動態配置的記憶體, malloc 及指標使用, 跟本次主題無關, 留待下次討論。
-
-
整理關於 global static extern 的常用規範 - 使用
-
當程式是多個檔案時,才有使用宣告的必要。
-
可以宣告很多次,但定義必須是唯一的!
-
多檔案下的宣告,編譯器會自動從所有檔案中尋找它的定義。
-
原則為:『把宣告寫在.h檔,把定義寫在.c檔』
-
不要在宣告變數時,設定初始值!在宣告變數的同時設定初始值,會轉變成定義。
-
定義變數,沒有設定初始值,其值是無法保證的。
-
習慣上 Global 變數會以大寫字母開頭, 有別於 local 變數
-
在 C/C++ 程式中, 變數的宣告和變數的使用愈靠近愈好 就是這裡所謂的最小範疇原則。

整理關於 global static extern 的常用規範 - 總整理
Global / Local 變數的例子
-
為什麼結果是 3, 5, 5, 5 ?
#include <stdio.h>
static int shared = 3; /* This is the file-scope variable (with
* internal linkage), visible only in
* this compilation unit.
*/
extern int overShared = 1; /* This one has external linkage (not
* limited to this compilation unit).
*/
int overSharedToo = 2; /* Also external linkage
*/
static void changeShared(void)
{
shared = 5; /* Reference to the file-scope
* variable in a function.
*/
}
static void localShadow(void)
{
int shared; /* local variable that will hide
* the global of the same name
*/
shared = 1000; /* This will affect only the local variable and will
* have no effect on the file-scope variable of the
* same name.
*/
}
static void paramShadow(int shared)
{
shared = -shared; /* This will affect only the parameter and will have no
* effect on the file-scope variable of the same name.
*/
}
int main(void)
{
printf("%d\n", shared); /* Reference to the file-scope variable. */
changeShared();
printf("%d\n", shared);
localShadow();
printf("%d\n", shared);
paramShadow(1);
printf("%d\n", shared);
return 0;
}Global/Static/Extern variables in C/C++ language
By Marconi Jiang
Global/Static/Extern variables in C/C++ language
Global/Static/Extern variables in C/C++ language
- 237