基本概念: 做用域:起做用的區域,也就是能夠工做的範圍。函數
代碼塊:所謂代碼塊,就是用{}括起來的一段代碼。this
數據段:數據段存的是數,像全局變量就是存在數據段的spa
代碼段:存的是程序代碼,通常是隻讀的。code
棧(stack):先進後出。C語言中局部變量就分配在棧中。blog
局部變量生命週期
普通的局部變量定義的時候直接定義或者在前面加上auto作用域
void func1(void)
{
int i = 1;
i++;
printf("i = %d.\n", i);
}
局部變量i的解析:
在連續三次調用func1中,每次調用時,在進入函數func1後都會創造一個新的變量i,
而且給它賦初值1,而後i++時加到2,
而後printf輸出時輸出2.而後func1本次調用結束,
結束時同時殺死本次創造的這個i。這就是局部變量i的整個生命週期。
下次再調用該函數func1時,又會從新創造一個i,經歷整個程序運算,
最終在函數運行完退出時再次被殺死。編譯器
靜態局部變量(static) 靜態局部變量定義時前面加static關鍵字。io
總結: 編譯
一、靜態局部變量和普通局部變量不一樣。靜態局部變量也是定義在函數內部的,靜態局部變量定義時前面要加static關鍵字來標識,靜態局部變量所在的函數在多調用屢次時,只有第一次才經歷變量定義和初始化,之後屢次在調用時再也不定義和初始化,而是維持以前上一次調用時執行後這個變量的值。本次接着來使用。
二、靜態局部變量在第一次函數被調用時創造並初始化,但在函數退出時它不死亡,而是保持其值等待函數下一次被調用。下次調用時再也不從新創造和初始化該變量,而是直接用上一次留下的值爲基礎來進行操做。
三、靜態局部變量的這種特性,和全局變量很是相似。它們的相同點是都創造和初始化一次,之後調用時值保持上次的不變。不一樣點在於做用域不一樣
全局變量 定義在函數外面的變量,就叫全局變量。
普通全局變量 普通全局變量就是平時使用的,定義前不加任何修飾詞。普通全局變量能夠在各個文件中使 用,能夠在項目內別的.c文件中被看到,因此要確保不能重名。
靜態全局變量 靜態全局變量就是用來解決重名問題的。靜態全局變量定義時在定義前加static關鍵字, 告訴編譯器這個變量只在當前本文件內使用,在別的文件中絕對不會使用。這樣就不用擔憂重名問題。因此靜態的全局變量就用在我定義這個全局變量並非爲了給別的文件使用,原本就是給我這個文件本身使用的。
跨文件引用全局變量(extern) 就是說,你在一個程序的多個.c源文件中,能夠在一個.c文件中定義全局變量g_a,而且能夠在別的另外一個.c文件中引用該變量g_a(引用前要聲明)
函數和全局變量在C語言中能夠跨文件引用,也就是說他們的鏈接範圍是全局的,具備文件鏈接屬性,總之意思就是全局變量和函數是能夠跨文件看到的(直接影響就是,我在a.c和b.c中各自定義了一個函數func,名字相同可是內容不一樣,編譯報錯。)。
局部變量和全局變量的對比:
一、定義同時沒有初始化,則局部變量的值是隨機的,而全局變量的值是默認爲0.
二、使用範圍上:全局變量具備文件做用域,而局部變量只有代碼塊做用域。
三、生命週期上:全局變量是在程序開始運行以前的初始化階段就誕生,到整個程序結束退出的時候才死亡;而局部變量在進入局部變量所在的代碼塊時誕生,在該代碼塊退出的時候死亡。
四、變量分配位置:全局變量分配在數據段上,而局部變量分配在棧上。
//static
1 #include <stdio.h> 2 3 4 void func1(void); 5 void func_static(void); 6 void func_static2(void); 7 void func_global(void); 8 void func_register(void); 9 10 int g_a = 1; 11 12 13 int main(void) 14 { 15 //a = 4; // 編譯報錯,未定義 16 g_a = 5; // 能夠,由於g_a是全局變量,因此處處均可以用 17 18 func1(); // i = 2 19 func1(); // i = 2 20 func1(); // i = 2 21 22 func_static(); // a = 2 23 func_static(); // a = 3 24 func_static(); // a = 4 25 26 func_static2(); // a = 4; 27 func_static2(); // a = 7; 28 func_static2(); // a = 10; 29 30 func_global(); // g_a = 4; 31 func_global(); // g_a = 7; 32 func_global(); // g_a = 10; 33 34 func_register(); 35 func_register(); 36 func_register(); 37 38 39 40 41 // 由於i是定義在函數func中的局部變量,因此i的做用域爲代碼塊做用域,因此i只在func1 42 // 函數內部有效,在func1外面是不能訪問i的。因此這裏i會無定義。 43 //i = 5; // error: ‘i’ undeclared (first use in this function) 44 45 return 0; 46 } 47 48 49 void func1(void) 50 { 51 int i = 1; // 普通的局部變量,auto能夠省略的 52 //auto int i = 0; // 自動局部變量,其實就是普通局部變量 53 54 i++; 55 56 printf("i = %d.\n", i); 57 } 58 59 void func_static(void) 60 { 61 static int a = 1; // 靜態的局部變量 62 63 a++; 64 65 printf("a = %d.\n", a); 66 } 67 68 void func_static2(void) 69 { 70 static int a = 1; // 靜態的局部變量 71 72 a += 3; 73 74 printf("a = %d.\n", a); 75 } 76 77 void func_global(void) 78 { 79 g_a += 3; 80 81 printf("g_a = %d.\n", g_a); 82 } 83 84 void func_register(void) 85 { 86 register int a = 1; // 靜態的局部變量 87 88 a += 3; 89 90 printf("a = %d.\n", a); 91 }
//globle
1 #include <stdio.h> 2 3 4 int g_i = 13; 5 6 7 // 實驗結論: 8 // 首先,main函數是一個程序運行最開始執行的東西,全部的其餘函數都只能在main函數中被 9 // 直接或者間接的調用才能被執行。main函數的執行其實就是整個程序的生命週期,main函數 10 // 一return返回,整個程序就結束了。 11 // 其次,全局變量的定義和初始化是在main函數運行以前發生的。 12 int main(void) 13 { 14 printf("g_i = %d.\n", g_i); 15 16 return 0; 17 }
1 #include <stdio.h> 2 3 4 void func_in_a(void); 5 extern int g_a; // 聲明瞭一個int變量g_a 6 //extern int g_b; 7 8 void func_in_b(void) 9 { 10 printf("I am func in b.c.\n"); 11 } 12 13 14 int main(void) 15 { 16 printf("I am main in a.c.\n"); 17 printf("I am main in a.c, g_a = %d.\n", g_a); 18 printf("I am main in a.c, g_a = %d.\n", g_b); 19 20 21 //func_in_b(); // 直接調用 22 23 func_in_a(); // 間接調用 24 25 return 0; 26 }
1 #include <stdio.h> 2 3 4 5 void func_in_b(void); 6 7 int g_a = 12; 8 int g_b = 111; 9 10 11 12 13 14 15 void func_in_a(void) 16 { 17 18 g_a = 24; 19 20 printf("I am in func_in_a of a.c, g_a = %d.\n", g_a); 21 func_in_b(); 22 } 23 24 /* 25 // 定義錯誤 26 // C語言中,定義函數都必須在外面,不能在一個函數裏面定義別的函數 27 // 因此沒有局部函數,只有全局函數。 28 29 void func1(void) 30 { 31 int a; 32 33 34 void func2() 35 { 36 int b; 37 } 38 } 39 40 */
//最後兩個分別爲a.c b.c 文件目錄爲