C 標識符作用域分三種:局部、全局、文件。作用域決定標識符在程序中的可見性,通常通過聲明位置隱式確定。
函數內部聲明的變量屬局部作用域,僅在該函數語句塊可見。形式參數亦屬局部作用域。同名變量在不同函數互不干擾:
void add(int);
main() { int num=5; add(num); printf("%d\n",num); } // 輸出 5
void add(int num) { num++; printf("%d\n",num); } // 輸出 6
所有函數外部聲明的變量為全局變量,程序任何位置可訪問。一處修改,全局生效:
int num;
main() { int n=5; add(n); printf("%d\n",num); } // 輸出 6
void add(num) { num++; printf("%d\n",num); } // 輸出 6
static 修飾外部標識符賦予文件作用域,僅在定義它的轉換單元(源文件及包含的頭文件)內可見。多文件工程中防止同名全局變量衝突:
static int num; static void add(int);
main() { scanf("%d",&num); add(num); printf("%d\n",num); }
void add(num) { num++; }
聲明變量可通過存儲類型修飾符指定:auto、static、extern、register。
auto 指定局部變量為自動的,每次進入語句塊創建新拷貝並初始化。局部變量默認即為 auto,關鍵字可省略。函數參數默認也為自動。
對局部變量,static 與 auto 相對:作用域仍局限於語句塊,但生存期贯穿整個程序。初始化僅在首次執行生效,之後保持上次值:
// 1.c 自動變量
int add() { int num=50; num++; return num; }
// 輸出: 51 51 51
// 2.c 靜態變量
int add() { static int num=50; num++; return num; }
// 輸出: 51 52 53
未顯式初始化的靜態變量默認為 0。常用於遞歸函數、累加計數等場景。
extern 聲明在其他轉換單元定義的變量。編譯時不分配空間,鏈接時解析地址:
/* 1.c */
extern int num; void a();
main() { a(); printf("%d\n",num); } // 輸出 5
/* 2.c */
int num; void a() { num=5; }
結合 static 可實現模塊級封裝:文件內 static 全局變量對其他文件不可見,配合 extern 實現受控共享。
register 建議將局部變量存入 CPU 寄存器提高訪問速度。限制:無法取地址(&),編譯器可忽略建議。現代編譯器優化極佳,手動指定意義有限,但可作為優化器參考。