?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
每個出現(xiàn)在C程序中的標識符都是可見的(也就是說可以使用),只能在源代碼的一些可能不連續(xù)的部分稱為它的范圍。
在一個范圍內(nèi),只有當實體位于不同的名稱空間時,標識符才可以指定多個實體。
C有四種范圍:
塊范圍
文件范圍
功能范圍
函數(shù)原型范圍
如果由同一標識符命名的兩個不同實體同時在范圍內(nèi),并且它們屬于同一名稱空間,則范圍是嵌套的(不允許其他形式的范圍重疊),并且出現(xiàn)在內(nèi)部范圍內(nèi)的聲明隱藏出現(xiàn)在外部范圍中的聲明:
// The name space here is ordinary identifiers. int a; // file scope of name a begins here void f(void){ int a = 1; // the block scope of the name a begins here; hides file-scope a { int a = 2; // the scope of the inner a begins here, outer a is hidden printf("%d\n", a); // inner a is in scope, prints 2 } // the block scope of the inner a ends here printf("%d\n", a); // the outer a is in scope, prints 1} // the scope of the outer a ends here void g(int a); // name a has function prototype scope; hides file-scope a
在復合語句中聲明的任何標識符的范圍,包括函數(shù)體,或在if,switch,for,while或do-while語句(自C99以后)中出現(xiàn)的任何表達式,聲明或語句中,或者在參數(shù)列表中一個函數(shù)定義從聲明的地方開始,并在聲明塊或聲明結(jié)束時結(jié)束。
void f(int n) // scope of the function parameter 'n' begins{ // the body of the function begins ++n; // 'n' is in scope and refers to the function parameter// int n = 2; // error: cannot redeclare identifier in the same scope for(int n = 0; n<10; ++n) { // scope of loop-local 'n' begins printf("%d\n", n); // prints 0 1 2 3 4 5 6 7 8 9 } // scope of the loop-local 'n' ends // the function parameter 'n' is back in scope printf("%d\n", n); // prints the value of the parameter} // scope of function parameter 'n' endsint a = n; // Error: name 'n' is not in scope
在C99之前,選擇和迭代語句沒有建立它們自己的塊范圍(盡管如果在語句中使用復合語句,它具有通常的塊范圍):enum {a,b}; int不同(void){if(sizeof(enum {b,a})!= sizeof(int))返回a; // a == 1 return b; // C89中的b == 0,C99中的b == 1} | (自C99以來) |
---|
默認情況下,塊范圍變量沒有鏈接和自動存儲持續(xù)時間。請注意,非VLA局部變量的存儲時間在輸入塊時開始,但直到看到聲明,該變量不在范圍內(nèi)且無法訪問。
在任何塊或參數(shù)列表之外聲明的任何標識符的范圍從聲明點開始,并在翻譯單元結(jié)束時結(jié)束。
int i; // scope of i beginsstatic int g(int a) { return a; } // scope of g begins (note, "a" has block scope)int main(void){ i = g(2); // i and g are in scope}
文件范圍標識符默認具有外部鏈接和靜態(tài)存儲持續(xù)時間。
在函數(shù)中聲明的標簽(只有標簽)在該函數(shù)中的任何位置,在所有嵌套塊中,在它自己的聲明之前和之后。注意:通過在任何語句之前的冒號字符之前使用未使用的標識符來隱式聲明標簽。
void f(){ { goto label; // label in scope even though declared laterlabel:; } goto label; // label ignores block scope} void g(){ goto label; // error: label not in scope in g()}
在函數(shù)聲明的參數(shù)列表中引入的不是定義的名稱的作用域結(jié)束于函數(shù)聲明器的末尾。
int f(int n, int a[n]); // n is in scope and refers to the first parameter
請注意,如果聲明中有多個或嵌套的聲明符,則該作用域?qū)⒃谧罱姆忾]函數(shù)聲明符的末尾結(jié)束:
void f ( // function name 'f' is at file scope long double f, // the identifier 'f' is now in scope, file-scope 'f' is hidden char (**a)[10 * sizeof f] // 'f' refers to the first parameter, which is in scope); enum{ n = 3 };int (*(*g)(int n))[n]; // the scope of the function parameter 'n' // ends at the end of its function declarator // in the array declarator, global n is in scope// (this declares a pointer to function returning a pointer to an array of 3 int)
結(jié)構(gòu)體,聯(lián)合體和枚舉標簽的范圍在標簽出現(xiàn)在聲明標簽的類型說明符后立即開始。
struct Node { struct Node* next; // Node is in scope and refers to this struct};
枚舉常量的范圍在枚舉器列表中出現(xiàn)其定義枚舉器后立即開始。
enum { x = 12 };{ enum { x = x + 1, // new x is not in scope until the comma, x is initialized to 13 y = x + 1 // the new enumerator x is now in scope, y is initialized to 14 };}
任何其他標識符的范圍都在其聲明符結(jié)束后并在初始化程序之前(如果有)開始:
int x = 2; // scope of the first 'x' begins{ int x[x]; // scope of the newly declared x begins after the declarator (x[x]). // Within the declarator, the outer 'x' is still in scope. // This declares a VLA array of 2 int.} unsigned char x = 32; // scope of the outer 'x' begins{ unsigned char x = x; // scope of the inner 'x' begins before the initializer (= x) // this does not initialize the inner 'x' with the value 32, // this initializes the inner 'x' with its own, indeterminate, value} unsigned long factorial(unsigned long n)// declarator ends, 'factorial' is in scope from this point{ return n<2 ? 1 : n*factorial(n-1); // recursive call}
作為一種特殊情況,不是標識符聲明的類型名稱的范圍被認為是在類型名稱中出現(xiàn)標識符的地方之后開始的,因為它不會被省略。
在C89之前,即使在塊內(nèi)引入外部鏈接的標識符也具有文件范圍,因此,C89編譯器不需要診斷使用超出范圍的外部標識符(這種用法是未定義的行為) 。
循環(huán)體內(nèi)的局部變量可以隱藏在C語言的for循環(huán)的init子句中聲明的變量(它們的作用域是嵌套的),但在C ++中不能這樣做。
與C ++不同,C沒有結(jié)構(gòu)范圍:在struct / union / enum聲明中聲明的名稱與結(jié)構(gòu)聲明在同一個范圍內(nèi)(除了數(shù)據(jù)成員在它們自己的成員名稱空間中):
struct foo { struct baz {}; enum color {RED, BLUE};};struct baz b; // baz is in scopeenum color x = RED; // color and RED are in scope