10:30:22 2019-08-20
基礎不牢 瞬間爆炸
參考資料:https://blog.csdn.net/ts_54eagle/article/details/4418627
https://blog.csdn.net/xingjiarong/article/details/47656339
https://blog.csdn.net/xingjiarong/article/details/47656339
看看C Primer Plus上是怎么定義的
先說說作用域 分為4種:塊作用域 函數作用域 函數原型作用域 文件作用域
這里要說明的是 塊作用域指{}之間的部分
而函數作用域單單指goto標簽 當goto標簽出現在函數內部時 goto標簽作用域蔓延至整個函數
函數原型作用域從形參定義到原型聲明結束為止
文件作用域指的是 該文件 該文件 該文件 從變量定義到文件末尾都可見
鏈接分為3種:外部鏈接 內部鏈接 無鏈接 (決定了是否能被外部文件使用)
塊作用域 函數作用域 函數原型作用域的變量 都屬於無鏈接
文件作用域的變量 可以屬於外部鏈接 也可屬於內部鏈接
內部鏈接的文件作用域 稱為 文件作用域(只能在該文件內部使用)
外部鏈接的文件作用域 稱為 全局作用域(整個程序都可使用)
一個具有文件作用域的變量默認是具有全局作用域的 在前面加上static變為具有文件作用域
C對象有4種存儲期:靜態存儲期、線程存儲期、自動存儲期、動態分配存儲期。
如果某個變量具有靜態存儲期,該變量在程序運行過程中一直存在 文件作用域具有靜態存儲期
在具有文件作用域的變量前加上static 表示該變量的作用域限制為內部鏈接
對於所有的具有文件作用域的變量(無論它具有內部鏈接還是外部鏈接)都具有靜態存儲期 而聲明了static的文件作用域的變量具有內部鏈接
存儲類別 | 存儲期 | 作用域 | 鏈接 | 聲明方式 |
自動 | 自動 | 塊 | 無 | 塊內 |
寄存器 | 自動 | 塊 | 無 | 塊內 使用關鍵字register |
靜態外部鏈接 | 靜態 | 文件 | 外部 | 所有函數外 |
靜態內部鏈接 | 靜態 | 文件 | 內部 | 所有函數外 使用關鍵字register |
靜態無鏈接 | 靜態 | 塊 | 無 | 塊內 使用關鍵字register |
auto: 默認情況下 聲明在塊內和函數頭中的變量都是auto類型的變量 也可以顯式的在變量聲明時寫上auto auto變量在使用時在棧上申請空間 使用結束后自動銷毀
register:寄存器變量存儲在寄存器中
static:對於局部變量來說 聲明為static 在使用時只會聲明一次 之后不會再聲明 對變量的改變會被保存(對它進行改變是在定義改變量的塊中 或者通過變量的指針)這樣改 局部變量具有了靜態存儲期
對於外部變量(具有文件作用域的變量)來說 static會將該變量聲明為內部鏈接
extern:用extern聲明 表明變量定義在別處 (extern也是聲明 是引用性聲明 不是定義性聲明)
在使用另外一個文件中的全局變量時要用extern聲明 這讓人有些迷惑 前面說 聲明為外部變量(未加static)具有全局作用域 那不就是能被其它文件使用了嗎 這樣的想法是錯誤的
c primer puls解釋的很清楚 :如果外部變量定義在一個文件中,那么其它文件在在使用該變量前必須先聲明它(用extern聲明)。也就是說,在某文件中對外部變量進行定義式聲明只是單方面允許其它文件使用改變量,其它文件在用extern聲明之前不能直接使用它
對於自動變量來說 未初始化 它中的數據是垃圾
對於具有靜態生存期的變量來說 如果未初始化 它里面的數據為0
例子:
main.c
1 #include <stdio.h> 2 void fun(); 3 int main() 4 { 5 fun(); 6 fun(); 7 return 0; 8 } 9 void fun() 10 { 11 int num2=5; 12 static int num1; 13 printf("num1 is:%d\n",num1); 14 printf("num2 is:%d\n",num2); 15 num1++; 16 num2++; 17 }
輸出結果:
可以看到 num1保存了上次的值
1 //file1.c 2 int num1=1; 3 static int num2=2; 4 5 //file.c 6 #include <stdio.h> 7 extern int num1; 8 extern int num2; //這句話只是說明num2是定義在另一個文件中的 但num2是不具有外部 9 //鏈接的 所以下面是無法使用的 10 int main() 11 { 12 printf("%d",num1); 13 //printf("%d",num2); //這句話是錯的 14 return 0; 15 }
1 //file1.c 2 #include<stdio.h> 3 void fun() 4 { 5 printf("fun()"); 6 } 7 8 //file2.c 9 #include <stdio.h> 10 extern void fun(); 11 int main() 12 { 13 fun(); 14 return 0; 15 }
extern也可以對函數進行引用式聲明