溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C語言中的變量作用域、鏈接和存儲期的意義是什么

發(fā)布時間:2021-05-31 13:49:02 來源:億速云 閱讀:144 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下C語言中的變量作用域、鏈接和存儲期的意義是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

在c中變量有三種性質(zhì):
1、存儲期限:變量的存儲期限決定了變量占用的內(nèi)存空間什么時候會被釋放,具有動態(tài)存儲期限的變量會在所屬的程序塊被執(zhí)行時獲得內(nèi)存空間,在結(jié)束時釋放內(nèi)存空間。具有靜態(tài)存儲期限的變量在程序運行的整個期間都會占用內(nèi)存空間。
2、作用域:變量有塊作用域也有文件作用域,結(jié)合序章第一張圖可以明白塊作用域是在某些程序塊內(nèi)起作用,文件作用域是在整個c文件之內(nèi)起作用。
3、鏈接:鏈接是各個文件之間的關(guān)系,具有內(nèi)部鏈接的變量只在本文件內(nèi)起作用,具有外部鏈接的變量可以在不同文件內(nèi)起作用。具有無鏈接的變量只在某一個文件的某個函數(shù)內(nèi)起作用。

C語言中的變量作用域、鏈接和存儲期的意義是什么

C變量作用域、鏈接和存儲期的含義

錯誤的定義C語言變量的作用域、鏈接和存儲區(qū)在某種程度上會直接影響程序的設計,我們通過這篇博文介紹如何正確合理的定義一個C變量。

從定義一個C變量開始成為一個C高手

一、基本術(shù)語   

1.1 什么是對象(object)

       C語言中的對象含義與C++的完全不同,C語言中的對象指的是存儲數(shù)據(jù)的一塊內(nèi)存。對象可以存儲一個或多個值,一個對象可能并未存儲實際的值,但是在存儲適當?shù)闹禃r一定具有相應的大小。對象可以存在于程序的執(zhí)行期,也可以僅存在于它所在函數(shù)的執(zhí)行期。

  1.2 什么是標識符(identifier)

       標識符就是一個名稱,通過這個標識符可以修改對象的內(nèi)容。標識符可以在源代碼的多文件中共享、可用于特定文件的任意函數(shù)中、可僅限于特定函數(shù)中使用,甚至只在函數(shù)中的某部分使用。

舉個例子,我們定義一個int型變量point:

int point;

對象與標識符的關(guān)系如下圖

C語言中的變量作用域、鏈接和存儲期的意義是什么

二、作用域、鏈接和存儲期三者關(guān)系

       存儲期用來描述對象,所謂的存儲期就是指對象在內(nèi)存中可以保留多長時間。

       標識符用于訪問對象,使用作用域(scope)和鏈接(linkage)描述標識符,標識符的作用域和鏈接表明了程序的哪些部分可以使用它。

三、作用域詳解

作用域描述程序中可訪問標識符的區(qū)域
一個C變量的作用域可以是塊作用域、函數(shù)作用域、函數(shù)原型作用域和文件作用域,下面我們詳細講解每個作用域的含義。

  3.1 塊作用域

       塊是用一對花括號括起來的代碼區(qū)域,定義在塊中的變量具有塊作用域,塊作用域變量的可見范圍是從定義處到包含該定義的塊的末尾。

       另外,雖然函數(shù)的形式參數(shù)聲明在函數(shù)的左花括號之前,但它們也具有塊作用域,屬于函數(shù)體這個塊。

int Star_CongShanRuoShui(int user_id)
{
	int res = 0;
	......
	return 
}

?上面code中“user_id”和“res”都具有塊作用域

int Star_CongShanRuoShui(int user_id[] , int n)
{
	int res = 0;
	for(int i=0;i<n;++i)
	{
		......
		int q=0;   //q的作用域開始
		
		......
	}              //q的作用域結(jié)束
	......
	return 
}

?上面code中變量“q”的作用域僅限于for循環(huán)的循環(huán)體中

    3.1.1 塊概念的擴展

       C99將塊概念擴展到包括for循環(huán)、while循環(huán)、do while循環(huán)和if語句所控制的代碼,即使這些代碼沒有使用花括號括起來,也算是塊的一部分,下面的code?

#include<stdio.h>

int main()
{
	int Star_CSRS = 8;
	printf("[main] value of Star_CSRS is %d | address of Star_CSRS:%p\n",
			Star_CSRS ,&Star_CSRS);
	
	for(int Star_CSRS=0;Star_CSRS<4;++Star_CSRS)
	{
		printf("[for index] value of Star_CSRS is %d | address of Star_CSRS:%p\n",
			Star_CSRS ,&Star_CSRS);
			
		int Star_CSRS = 6;
		printf("[for] value of Star_CSRS is %d | address of Star_CSRS:%p\n",
			Star_CSRS ,&Star_CSRS);
		
		++Star_CSRS;
	}
	
	printf("[main] value of Star_CSRS is %d | address of Star_CSRS:%p\n",
			Star_CSRS ,&Star_CSRS);

	return 0;
}

輸出如下:

C語言中的變量作用域、鏈接和存儲期的意義是什么

  • 在main中定義了變量Star_CSRS,在for循環(huán)頭中定義的變量Star_CSRS 隱藏了main中的Star_CSRS

  • for的循環(huán)體中的Star_CSRS又隱藏了for循環(huán)頭中的Star_CSRS

C語言中的變量作用域、鏈接和存儲期的意義是什么  

 3.2 函數(shù)作用域

       函數(shù)作用域的概念僅限于goto語句的標簽。這意味著即使一個標簽首次出現(xiàn)在函數(shù)的內(nèi)層塊中,它的作用域也延伸至整個函數(shù)中(詳細可以參考我的這篇博文)。

3.3 函數(shù)原型作用域

       用于函數(shù)原型的形參變量名,如下所示:

int Star_CongShanRuoShui(int user_id);

       函數(shù)原型作用域的范圍是從形參定義處到原型聲明結(jié)束。對于函數(shù)原型中的形參編譯器只關(guān)心形參類型,不關(guān)系具體的形參名,即使有形參名也不必與函數(shù)定義中的形參名相匹配

       只有在變長數(shù)組中,形參名才有意義,如下例(變長數(shù)組詳細參考我的這篇博文):

int Star_CongShanRuoShui(int n ,int user_id[n]);

  3.4 文件作用域

       定義在所有函數(shù)外的變量具有文件作用域。具有文件作用域的變量,從它的定義處到該定義所在文件的末尾均可見(文件作用域變量也稱為全局變量)。

翻譯單元與文件

編譯器將一個源代碼文件和所有的頭文件都看成一個包含信息的單獨文件,這個文件被稱為翻譯單元一個翻譯單元包括一個源代碼文件和它所include的文件如果一個程序有多個源代碼文件,那么這個程序也將有多個翻譯單元一個文件作用域變量的可見范圍其實是整個翻譯單元(一個源代碼文件+頭文件)

四、鏈接詳解

C變量有3中鏈接屬性:無鏈接、內(nèi)部鏈接、外部鏈接

  4.1 無鏈接

       具有塊作用域、函數(shù)作用域和函數(shù)原型作用域的變量都是無鏈接變量。這意味著這些變量屬于定義它們的塊、函數(shù)或原型私有。

  4.2 內(nèi)部鏈接

       內(nèi)部鏈接變量只能在一個翻譯單元中使用,該變量使用存儲類別說明符static修飾,如下:

int Star_CSDN=1;                     //文件作用域,外部鏈接
static int Star_CongShanRuoShui=2;   //文件作用域,內(nèi)部鏈接

int main()
{
	......
	return 0
}

  4.3 外部鏈接

       外部鏈接變量可以在多個文件中使用。外部鏈接變量的聲明分為“定義性聲明”和“引用性聲明”。C編譯器要求一個變量只能定義一次,重復定義編譯器會報錯。如果需要在其它文件中使用外部鏈接變量需要使用extern引用性聲明這個變量,如下面cdoe:

//file a.c

//在文件a.c中定義一個外部鏈接變量Star_CongShanRuoShui
int Star_CongShanRuoShui = 2;

......
//file b.c

//文件b.c中使用extern引用性聲明變量Star_CongShanRuoShui
extern int Star_CongShanRuoShui;

......

五、存儲期詳解

C對象有4種存儲期:靜態(tài)存儲期、線程存儲期、自動存儲期、動態(tài)分配存儲期。

  5.1 靜態(tài)存儲期

       具有靜態(tài)存儲期的對象,它在程序的執(zhí)行期間一直存在。文件作用域變量具有靜態(tài)存儲期

注意,對于文件作用域變量,關(guān)鍵字static表明了其鏈接屬性,而非存儲期。以static聲明的文件作用域變量具有內(nèi)部鏈接屬性,但是無論是內(nèi)部鏈接還是外部鏈接,所有文件作用域變量都具有靜態(tài)存儲期。

  5.2 線程存儲期

       線程存儲期用于并發(fā)程序設計,程序執(zhí)行可被分為多個線程。具有線程存儲期的對象,從被聲明時到線程結(jié)束一直存在。以關(guān)鍵字__Thread_local聲明一個對象時,每個線程都獲得這個變量的私有備份

  5.3 自動存儲期

       塊作用域的變量通常都具有自動存儲期。當程序進入定義這些變量的塊時,為這些變量分配內(nèi)存;當退出這個塊時,釋放剛才為這些變量分配的內(nèi)存。通過這種做法可以實現(xiàn)內(nèi)存的重復利用。

變長數(shù)組稍有例外,它的存儲期從聲明處到塊的末尾,而不是從塊的開始處到塊的末尾

       我們上面說塊作用域的變量通常都具有自動存儲期,但是也能具有靜態(tài)存儲期。為了創(chuàng)建這樣的變量,要把變量聲明在塊中,且在聲明前加上關(guān)鍵字static,如下例:

int Star_CongShanRuoShui(int user_id)
{
	static int isStar = 0;
	......
	return 
}

       變量isStar存儲在靜態(tài)內(nèi)存中,它從程序被載入到程序結(jié)束期間都存在。但是,它的作用域定義在Star_CongShanRuoShui()函數(shù)塊中,只有在執(zhí)行該函數(shù)時,程序才能使用isStar訪問它所指定的對象(當然,也可以存儲該變量的地址實現(xiàn)間接訪問該對象)

 5.4 動態(tài)分配存儲期

       程序運行時通過malloc()等內(nèi)存分配函數(shù)分配的對象具有動態(tài)分配存儲期,這樣的對象需要使用free()函數(shù)進行銷毀。

動態(tài)內(nèi)存分配和變長數(shù)組在功能上有些重合,但是還是有所不同:

變長數(shù)組是自動存儲類型用malloc函數(shù)創(chuàng)建的數(shù)組不必局限在一個函數(shù)中使用

以上是“C語言中的變量作用域、鏈接和存儲期的意義是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI