十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
這篇文章主要講解了“C語言中的作用域、鏈接、存儲期的概念”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C語言中的作用域、鏈接、存儲期的概念”吧!
創(chuàng)新互聯(lián)是一家專注于做網(wǎng)站、網(wǎng)站建設與策劃設計,朔州網(wǎng)站建設哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設10多年,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:朔州等地區(qū)。朔州做網(wǎng)站價格咨詢:13518219792
C 程序中出現(xiàn)的每個標識符都僅在一些可能不連續(xù)的部分可見(即可使用),這些部分被稱為其作用域。作用域描述程序中可訪問標識符的區(qū)域。
C 擁有四種作用域:
塊作用域
函數(shù)作用域
函數(shù)原型作用域
文件作用域
任何在復合語句,包含函數(shù)體或出現(xiàn)于 if 、 switch 、 for 、 while 或 do-while 語句中的任何表達式、聲明或語句 (C99 起),或在函數(shù)定義內的參數(shù)列表中聲明的標識符的作用域,在聲明點開始,在聲明于其中的塊或語句的結尾結束。
聲明于函數(shù)內部的標號(且只有標號),在該函數(shù)中的所有位置(所有嵌套塊中,其自身聲明前后)都在作用域內。注意:任何語句前的冒號字符前的標識符,若不用于其他用途,則隱式聲明一個標號。
void f() { { goto label; // label 在作用域中,盡管之后才聲明 label:; } goto label; // 標號忽略塊作用域 } void g() { goto label; // 錯誤: g() 中 label 不在作用域中 }
非函數(shù)定義的函數(shù)聲明的參數(shù)列表中引入的名稱的作用域,在函數(shù)聲明器的結尾結束。
int f(int n, int a[n]); // n 在作用域中并指代第一參數(shù)
在任何塊或參數(shù)列表外聲明的任何標識符的作用域,在聲明點開始,翻譯單元尾結束。
int i; // i 的作用域開始 static int g(int a) { return a; } // g 的作用域開始(注意 "a" 擁有塊作用域) int main(void) { i = g(2); // i 和 g 在作用域中 }
若相同標識符所命名的二個不同實體在同一時刻都在作用域中,且它們屬于同一命名空間,則作用域被嵌套(不允許其他形式的作用域重疊),而內層作用域中的聲明隱藏外層作用域中的聲明:
// 此處的命名空間為通常標識符。 int a; // 名稱 a 的文件作用域始于此 void f(void) { int a = 1; // 名稱 a 的塊作用域始于此;隱藏文件作用域的 a { int a = 2; // 內層 a 的作用域始于此,隱藏外層 a printf("%d\n", a); // 內層 a 在作用域中,打印 2 } // 內層 a 的塊作用域終于此 printf("%d\n", a); // 外層 a 在作用域中,打印 1 } // 外層 a 的作用域終于此 void g(int a); // 名稱 a 擁有函數(shù)原型作用域;隱藏文件作用域的 a
注意,若聲明中有多個或嵌套聲明器,則作用域在最近的外圍函數(shù)聲明器的結尾結束:
void f ( // 函數(shù)名 'f' 在文件作用域 long double f, // 標識符 'f' 現(xiàn)在在作用域中,隱藏文件作用域的 'f' char (**a)[10 * sizeof f] // 'f' 指代第一參數(shù),它在作用域中 ); enum{ n = 3 }; int (*(*g)(int n))[n]; // 函數(shù)參數(shù) 'n' 的作用域在其函數(shù)聲明器的結尾結束 // 數(shù)組聲明器中,全局 n 在作用域 // (這聲明指向返回 3 個 int 的數(shù)組的指針的函數(shù)的指針)
結構體、聯(lián)合體及枚舉標簽的作用域,在聲明該標簽的類型指定符中的標簽出現(xiàn)后立即開始。
struct Node { struct Node* next; // Node 在作用域中并指代此 struct };
枚舉常量的作用域,在枚舉項列表中其定義枚舉項的出現(xiàn)后立即開始。
enum { x = 12 }; { enum { x = x + 1, // 新 x 在逗號前不在作用域中,初始化 x 為 13 y = x + 1 // 新枚舉項 x 現(xiàn)在在作用域中,初始化 y 為 14 }; }
任何其他標識符的作用域,正好在其聲明器結束后和初始化器前開始,若存在初始化器:
int x = 2; // 第一個 'x' 的作用域開始 { int x[x]; // 新聲明的 x 的作用域在聲明器 ( x[x] )后開始。 // 在聲明器內,外層 'x' 仍在作用域中。 // 這聲明 2 個 int 的 VLA 數(shù)組。 } unsigned char y = 32; // 外層 'y' 的作用域開始 { unsigned char y = y; // 內層 'y' 的作用域在初始化器( = y )前開始 // 這不會以值 32 初始化內層 'y' , // 這以其自身的不確定值初始化內層 'y' } unsigned long factorial(unsigned long n) // 聲明器結束, 'factorial' 從此點開始在作用域中 { return n < 2 ? 1 : n * factorial(n - 1); // 遞歸調用 }
鏈接指的是在其他作用域指代一個標識符(具名對象或函數(shù))的能力。若在數(shù)個作用域中聲明有同一標識符的對象或函數(shù),但不能從所有這些作用域指代它們,則會創(chuàng)建數(shù)個對象的實例。
C 變量具有3種鏈接屬性:
外部鏈接
內部鏈接
無鏈接
只能從其所在的作用域指代該標識符。
所有函數(shù)參數(shù)
所有非 extern 的塊作用域對象(包含聲明為 static 者)
能從當前翻譯單元的所有作用域指代該標識符。在一個翻譯單元內,帶內部鏈接的標識符的每個實例均表示相同的標識符或函數(shù)。 內部鏈接的標識符對于翻譯單元是唯一的。
所有 static 文件作用域標識符(函數(shù)和對象)
能從整個程序的任何其他翻譯單元指代該標識符。具有外部鏈接的標識符的名稱指定相同的函數(shù)或數(shù)據(jù)對象,這與具有外部連接的相同名稱的任何其他聲明一樣。 這兩個聲明可以在同一個翻譯單元中,也可以在不同的翻譯單元中。 如果該對象或函數(shù)還具有全局生存期,則該對象或函數(shù)由整個程序共享。
所有非 static 函數(shù)
所有 extern 對象(除非之前聲明為 static )
所有文件作用域的非 static 對象擁有此鏈接。
若同一標識符在同一翻譯單元中一同帶內部和外部鏈接出現(xiàn),則行為未定義。這在使用試探性定義時有可能。
每個對象都有稱為存儲期的屬性,它限制對象的生存期。 C 中有四種存儲期:
自動存儲期。
靜態(tài)存儲期。
線程存儲期。
分配存儲期。
如果對象具有自動存儲期,那么它存在于,程序進入定義這些變量的塊到退出這個塊。進入聲明對象于其中的塊時分配其存儲,而在以任何方式( goto 、 return 、抵達結尾)退出該塊時解分配存儲。
一個例外是 VLA ;在執(zhí)行聲明時而非塊入口分配其存儲,并在聲明離開作用域而非退出塊時解分配存儲。 (C99 起)若遞歸地進入塊,則對每個遞歸層進行新的分配。
以下變量具有自動存儲期:
非 static 塊作用域對象
所有函數(shù)參數(shù)
用于塊作用域的復合字面量
如果對象具有靜態(tài)存儲期,那么它在程序執(zhí)行期間一直存在。存儲期是整個程序的執(zhí)行過程,只在 main 函數(shù)之前初始化一次存儲于對象的值。
以下變量具有靜態(tài)存儲期:
所有聲明為 static 對象
所有帶內部或外部鏈接且不聲明為 _Thread_local (C11 起)的對象都擁有此存儲期。
存儲期是創(chuàng)建對象的線程的整個執(zhí)行過程,在啟動線程時初始化存儲于對象的值。每個線程擁有其自身的相異對象。若執(zhí)行訪問此對象的表達式的線程,不是執(zhí)行其初始化的線程,則行為是實現(xiàn)定義的。
以下變量具有靜態(tài)存儲期:
所有聲明為 _Thread_local 的對象(C11 起)
按照請求,用動態(tài)內存分配函數(shù)分配和解分配存儲。
感謝各位的閱讀,以上就是“C語言中的作用域、鏈接、存儲期的概念”的內容了,經(jīng)過本文的學習后,相信大家對C語言中的作用域、鏈接、存儲期的概念這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關知識點的文章,歡迎關注!