偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

學(xué)了這么久的C,作用域,存儲(chǔ)器,鏈接屬性該弄清楚了

開(kāi)發(fā) 后端
這些是編程語(yǔ)言中的基本概念,如果你還不是非常明確地清楚標(biāo)題的問(wèn)題,并且不知道作用域,鏈接屬性,存儲(chǔ)期等概念的具體含義,那么本文你不該錯(cuò)過(guò)。

[[352572]]

本文轉(zhuǎn)載自微信公眾號(hào)「編程珠璣」,作者守望先生。轉(zhuǎn)載本文請(qǐng)聯(lián)系編程珠璣公眾號(hào)。  

前言

這些是編程語(yǔ)言中的基本概念,如果你還不是非常明確地清楚標(biāo)題的問(wèn)題,并且不知道作用域,鏈接屬性,存儲(chǔ)期等概念的具體含義,那么本文你不該錯(cuò)過(guò)。為了更加清晰的理解我們的問(wèn)題,需要先了解三個(gè)概念:作用域,鏈接屬性,存儲(chǔ)期。

作用域

C語(yǔ)言中,作用域用來(lái)描述標(biāo)識(shí)符能夠被哪些區(qū)域訪問(wèn)。

而常見(jiàn)作用域有以下幾種:

  • 塊作用域,可見(jiàn)范圍是從定義處到包含該定義的塊結(jié)尾
  • 函數(shù)作用域,goto語(yǔ)句的標(biāo)簽就具有函數(shù)作用域
  • 文件作用域,從定義處到定義該文件的末尾都可見(jiàn)。定義在函數(shù)之外的變量,就具有文件作用域了。
  • 函數(shù)原型作用域,從形參定義處到原型聲明結(jié)束

為了便于說(shuō)明,我們來(lái)看一個(gè)例子,就很容易理解了:

  1. /**************************** 
  2. 作者:守望先生 
  3. 來(lái)源:公眾號(hào)編程珠璣 
  4. 個(gè)人博客:https://www.yanbinghu.com 
  5. ***************************************/ 
  6. #include <stdio.h> 
  7. int num1 = 222;         //定位在函數(shù)外,具有文件作用域 
  8. static int num2 = 111;  //定義在函數(shù)外,具有文件作用域 
  9. int swap(int *a,int *b); //這里的a,b是函數(shù)原型作用域 
  10. int swap(int *a,int *b) 
  11.     if(NULL== a || NULL == b) 
  12.         goto error;     
  13.     else 
  14.     { 
  15.         int temp = *a;  //定義在函數(shù)內(nèi),塊作用域 
  16.         *a = *b; 
  17.         *b = temp
  18.         return 0; 
  19.     } 
  20.     //printf("temp is %d\n",temp);   //因?yàn)?/span>temp具有塊作用域,因此在這里不能直接使用 
  21.     error://goto語(yǔ)句的標(biāo)簽,函數(shù)作用域,因此在前面就可以引用 
  22.         { 
  23.             printf("input para is NULL\n"); 
  24.             return -1; 
  25.         } 
  26. int main(void) 
  27.     printf("num1=%d,num2=%d\n",num1,num2); 
  28.     swap(&num1,&num2);  //num1 num2具有文件作用域,可以在main函數(shù)中直接使用 
  29.     printf("num1=%d,num2=%d",num1,num2); 
  30.     return 0; 

可以看到,error標(biāo)簽具有函數(shù)作用域,整個(gè)函數(shù)內(nèi)都可見(jiàn),而temp具有塊作用域,因此在大括號(hào)外部,不能直接使用它。而num1和num2具有文件作用域,因此main函數(shù)可以直接使用它。

鏈接屬性

在《hello程序是如何變成可執(zhí)行文件的》我們說(shuō)到了編譯的過(guò)程,最后一個(gè)步驟就是鏈接。鏈接屬性決定了在不同作用域的同名標(biāo)識(shí)符能否綁定到同一個(gè)對(duì)象或者函數(shù)。或者說(shuō),不同作用域的標(biāo)識(shí)符在編譯后是否是同一個(gè)實(shí)體。

c變量有三種鏈接屬性:

  • 外部鏈接,extern修飾的,或者沒(méi)有static修飾的具有文件作用域的變量具有外部鏈接屬性
  • 內(nèi)部鏈接,static修飾的具有文件作用域的變量具有內(nèi)部鏈接屬性
  • 無(wú)鏈接,塊作用域,函數(shù)作用域和函數(shù)原型作用域的變量無(wú)鏈接屬性

再稍作解釋?zhuān)瑳](méi)有static修飾,且具有文件作用域的變量,他們?cè)阪溄訒r(shí),多個(gè)同名標(biāo)識(shí)符的變量最終都綁定到同一個(gè)實(shí)體。而static修飾的具有文件作用域的變量就不一樣了,不同文件內(nèi),即便標(biāo)識(shí)符名字相同,它們也綁定到了不同的實(shí)體。

因此,如果我們希望某個(gè)變量或函數(shù)只在某一個(gè)文件使用,那么使用static修飾是一個(gè)很好的做法。

同樣的,來(lái)看一個(gè)例子。

  1. /**************************** 
  2. 作者:守望先生 
  3. 來(lái)源:公眾號(hào)編程珠璣 
  4. 個(gè)人博客:https://www.yanbinghu.com 
  5. ***************************************/ 
  6. #include <stdio.h> 
  7. int a = 5;   //文件作用域,外部鏈接屬性,其他文件可通過(guò)extern int a的方式使用該文件的a 
  8. static b = 6;  //文件作用域,內(nèi)部鏈接屬性,即便其他文件也有同名標(biāo)識(shí)符,它們也是不同的 
  9. int main(void) 
  10.     int sum = 0 ; //無(wú)鏈接屬性 
  11.     sum = a + b; 
  12.     printf("sum is %d\n",sum); 
  13.     return 0; 

從代碼中可以看到,a和b都具有文件作用域,a具有外部鏈接屬性,而b具有內(nèi)部鏈接屬性,sum具有塊作用域,因此無(wú)鏈接屬性。

存儲(chǔ)期

實(shí)際上作用域和鏈接屬性都描述了標(biāo)識(shí)符的可見(jiàn)性,而存儲(chǔ)期則描述了這些標(biāo)識(shí)符對(duì)應(yīng)的對(duì)象的生存期。存儲(chǔ)期,也分下面幾種:

  • 靜態(tài)存儲(chǔ)期,程序執(zhí)行期間一直都在,文件作用域的變量具有靜態(tài)存儲(chǔ)期
  • 自動(dòng)存儲(chǔ)期,它(變長(zhǎng)數(shù)組除外)從塊開(kāi)始,到塊末尾,因此,塊作用域的變量具有自動(dòng)存儲(chǔ)期,它在棧中存儲(chǔ),需要顯式初始化。
  • 動(dòng)態(tài)分配存儲(chǔ)期,即通過(guò)malloc分配內(nèi)存的變量。它在堆中存儲(chǔ),需要顯式初始。
  • 線程存儲(chǔ)期,從名字可以知道, 它與線程相關(guān),使用關(guān)鍵字_Thread_local聲明的變量具有線程存儲(chǔ)期,它從聲明到線程結(jié)束一直存在。
  • 關(guān)于初始化,可參考《C語(yǔ)言入坑指南-被遺忘的初始化》。

同樣地,我們通過(guò)下面的代碼來(lái)更好地理解存儲(chǔ)期

  1. /**************************** 
  2. 作者:守望先生 
  3. 來(lái)源:公眾號(hào)編程珠璣 
  4. 個(gè)人博客:https://www.yanbinghu.com 
  5. ***************************************/ 
  6. #include <stdio.h> 
  7. int num1 = 222;         //靜態(tài)存儲(chǔ)期 
  8. static int num2 = 111;  //靜態(tài)存儲(chǔ)期 
  9. int add(int a,int b) 
  10.     static int tempSum = 0;  //靜態(tài)存儲(chǔ)期 
  11.     tempSum = tempSum + a + b; 
  12.     return tempSum; 
  13. int main(void) 
  14.     printf("num1=%d,num2=%d\n",num1,num2); 
  15.     int sum = 0;  //自動(dòng)存儲(chǔ)期 
  16.     sum = add(num1,num2); 
  17.     printf("first time sum=%d\n",sum);//sum = 333 
  18.     sum = add(num1,num2); 
  19.     printf("second time sum=%d\n",sum); //sum = 666 
  20.     return 0; 

另外,如果我們通過(guò)nm命令查看編譯出來(lái)的程序文件的符號(hào)表,我們可以找到num1,num2,tempSum,而沒(méi)有sum,前者所用的內(nèi)存數(shù)量在編譯時(shí)就確定了。

  1. $ gcc -g -o lifetime lifetime.c  
  2. $ nm lifetime|grep num1 
  3. 0000000000601038 D num1 
  4. $ nm lifetime|grep num2 
  5. 000000000060103c d num2 
  6. $ nm lifetime|grep tempSum 
  7. 0000000000601044 b tempSum.2289 
  8. $ nm lifetime|grep sum 

什么全局變量,局部變量,靜態(tài)局部變量,靜態(tài)全局變量

到這里,我們就可以很容易區(qū)分上面的變量類(lèi)型了。實(shí)際上這里只是換了一種說(shuō)法:

全局:具有文件作用域的變量

靜態(tài):具有靜態(tài)存儲(chǔ)期或內(nèi)部鏈接屬性

局部:具有函數(shù)或塊作用域的變量

因而結(jié)合起來(lái),也就很好理解了。

  • 局部變量:函數(shù)或塊作用域的變量
  • 靜態(tài)局部變量:函數(shù)或塊作用域,靜態(tài)存儲(chǔ)期
  • 全局變量:具有文件作用域的變量
  • 靜態(tài)全局變量:內(nèi)部鏈接屬性的,具有文件作用域的變量

當(dāng)然,這僅僅是為了區(qū)分它們,這并不是它們的嚴(yán)格定義。更好的方法,是通過(guò)代碼來(lái)理解:

  1. #include <stdio.h> 
  2. int num1 = 222;         //全局變量 
  3. static int num2 = 111;  //靜態(tài)全局變量 
  4. int add(int a,int b) 
  5.     static int tempSum = 0;  //靜態(tài)局部變量 
  6.     tempSum = tempSum + a + b; 
  7.     return tempSum; 
  8. int main(void) 
  9.     printf("num1=%d,num2=%d\n",num1,num2); 
  10.     int sum = 0;  //局部變量 
  11.     sum = add(num1,num2); 
  12.     printf("first time sum=%d\n",sum);//sum = 333 
  13.     return 0; 

總結(jié)

本文總結(jié)如下:

  • 具有文件作用域的變量具有靜態(tài)存儲(chǔ)期,并且具有鏈接屬性
  • 不希望其他文件訪問(wèn)的文件作用域變量最好使用static修飾
  • static關(guān)鍵字的含義需要結(jié)合上下文來(lái)理解
  • 如果可以,全局變量應(yīng)該盡量避免使用,因?yàn)樗赡軒?lái)變量被意外修改
  • 使用動(dòng)態(tài)內(nèi)存通常比棧內(nèi)存慢,但是棧內(nèi)存很有限

參考

https://en.wikipedia.org/wiki/Global_variables

https://en.wikipedia.org/wiki/Local_variable

《C11標(biāo)準(zhǔn)文檔》

作者:守望,linux應(yīng)用開(kāi)發(fā)者,目前在公眾號(hào)【編程珠璣】分享Linux/C/C++/數(shù)據(jù)結(jié)構(gòu)與算法/工具等原創(chuàng)技術(shù)文章和學(xué)習(xí)資源。

 

責(zé)任編輯:武曉燕 來(lái)源: 編程珠璣
相關(guān)推薦

2021-05-09 22:26:36

Python函數(shù)變量

2017-03-31 15:30:09

2020-02-15 15:33:55

Python如何運(yùn)作

2022-04-07 08:37:05

鏈表技巧單鏈表

2021-05-27 21:18:56

谷歌Fuchsia OS操作系統(tǒng)

2020-03-30 09:22:03

AI語(yǔ)音技術(shù)機(jī)器視覺(jué)

2020-02-18 16:48:48

大腦CPU包裝

2018-06-08 10:12:10

Web緩存體系服務(wù)器

2021-03-11 15:49:44

人工智能深度學(xué)習(xí)

2022-05-30 08:05:11

架構(gòu)

2012-05-28 10:06:05

項(xiàng)目開(kāi)發(fā)項(xiàng)目管理開(kāi)發(fā)

2021-03-19 14:12:24

2024-12-10 13:00:00

C++引用

2024-01-12 08:26:16

Linux磁盤(pán)文件系統(tǒng)

2022-02-08 13:39:35

LinuxUNIX系統(tǒng)

2019-10-29 09:41:54

Kafka分布式

2021-03-22 09:27:44

PythonEXCEL熱點(diǎn)推薦

2019-08-26 10:36:38

Python操作系統(tǒng)高考

2021-04-28 11:35:06

Java框架日志

2021-05-28 06:16:28

藍(lán)牙Wi-FiNFC
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)