存储类、作用域、生命周期、链接属性
以下內(nèi)容源于朱有鵬嵌入式課程的學(xué)習(xí),如有侵權(quán),請(qǐng)告知?jiǎng)h除。
補(bǔ)充:https://blog.csdn.net/oqqHuTu12345678/article/details/71214255
一、概念集合
1、存儲(chǔ)類
(1)存儲(chǔ)類就是存儲(chǔ)類型,也就是描述C語(yǔ)言變量在何種地方存儲(chǔ)。
(2)內(nèi)存有多種管理方法:棧、堆、數(shù)據(jù)段、bss段、.text段(代碼段)……一個(gè)變量的存儲(chǔ)類屬性就是描述這個(gè)變量存儲(chǔ)在何種內(nèi)存段中。
?
- 譬如局部變量分配在棧上,所以它的存儲(chǔ)類就是棧;
- 顯式初始化為非0的全局變量分配在數(shù)據(jù)段,顯式初始化為0和沒有顯示初始化(默認(rèn)為0)的全局變量分配在bss段。
?
2、作用域
(1)作用域是描述這個(gè)變量起作用的代碼范圍。
(2)基本來(lái)說(shuō),C語(yǔ)言變量的作用域規(guī)則是代碼塊作用域。
?
- 即這個(gè)變量起作用的范圍是當(dāng)前的代碼塊。代碼塊就是一對(duì)大括號(hào){}括起來(lái)的范圍,所以一個(gè)變量的作用域是:這個(gè)變量定義所在的{}范圍內(nèi)從這個(gè)變量定義開始往后的部分。(這就解釋了為什么變量定義總是在一個(gè)函數(shù)的最前面)
?
3、生命周期
(1)生命周期是描述這個(gè)變量什么時(shí)候誕生(運(yùn)行時(shí)分配內(nèi)存空間給這個(gè)變量)及什么時(shí)候死亡(運(yùn)行時(shí)收回這個(gè)內(nèi)存空間,此后再不能訪問這個(gè)內(nèi)存地址,或者訪問這個(gè)內(nèi)存地址已經(jīng)和這個(gè)變量無(wú)關(guān)了)的。
(2)變量和內(nèi)存的關(guān)系,就和人(變量)去圖書館借書(內(nèi)存)一樣。變量的生命周期就好象我人借書的這段周期一樣。
(3)研究變量的生命周期可以我們理解程序運(yùn)行的一些現(xiàn)象、理解C語(yǔ)言的一些規(guī)則。
?
4、鏈接屬性
?
(1)程序從源代碼到最終可執(zhí)行程序,經(jīng)歷的過程:編譯、鏈接。
?
- 編譯階段就是把源代碼搞成.o目標(biāo)文件。
- 目標(biāo)文件里面有很多符號(hào)和代碼段、數(shù)據(jù)段、bss段等分段。
- 符號(hào)就是編程中的變量名、函數(shù)名等。
- 運(yùn)行時(shí)變量名、函數(shù)名能夠和相應(yīng)的內(nèi)存對(duì)應(yīng)起來(lái),靠符號(hào)來(lái)做鏈接的。
(2).o的目標(biāo)文件鏈接生成最終可執(zhí)行程序的時(shí)候,其實(shí)就是把符號(hào)和相對(duì)應(yīng)的段給鏈接起來(lái)。
?
(3)C語(yǔ)言中的符號(hào)有三種鏈接屬性:外連接屬性、內(nèi)鏈接屬性、無(wú)連接屬性。
?
二、linux下C程序的內(nèi)存映像
?
1、代碼段、只讀數(shù)據(jù)段
- 對(duì)應(yīng)著程序中的代碼(函數(shù)),代碼段在linux中又叫文本段(.text);
- 只讀數(shù)據(jù)段就是在程序運(yùn)行期間只能讀不能寫的數(shù)據(jù),const修飾的常量有可能是存在只讀數(shù)據(jù)段的(但是不一定,const常量的實(shí)現(xiàn)方法在不同平臺(tái)是不一樣的)
2、數(shù)據(jù)段、bss段
?
- 數(shù)據(jù)段存:1、顯式初始化為非0的全局變量;2、顯式初始化為非0的static局部變量
- bss段存:1、顯式初始化為0或者未顯式初始化的全局變量;2、顯式初始化為0或未顯式初始化的static局部變量。
?
3、堆
?
- C語(yǔ)言中什么樣變量存在堆內(nèi)存中?
- C語(yǔ)言不會(huì)自動(dòng)向堆中存放東西,堆的操作是程序員自己手工操作的。
- 程序員根據(jù)需求自己判斷要不要使用堆內(nèi)存,用的時(shí)候自己申請(qǐng),自己使用,完了自己釋放。
?
4、文件映射區(qū)
?
- 文件映射區(qū)就是進(jìn)程打開了文件后,將這個(gè)文件的內(nèi)容從硬盤讀到進(jìn)程的文件映射區(qū),以后就直接在內(nèi)存中操作這個(gè)文件,讀寫完了后在保存時(shí)再將內(nèi)存中的文件寫到硬盤中去。
?
5、棧
- 局部變量分配在棧上;函數(shù)調(diào)用傳參過程也會(huì)用到棧
7、內(nèi)核映射區(qū)
?
- 內(nèi)核映射區(qū)就是將操作系統(tǒng)內(nèi)核程序映射到這個(gè)區(qū)域了。
- 對(duì)于linux中的每一個(gè)進(jìn)程來(lái)說(shuō),它都以為整個(gè)系統(tǒng)中只有它自己和內(nèi)核而已。
- 它認(rèn)為內(nèi)存地址0xC0000000以下都是它自己的活動(dòng)空間,0xC0000000以上是OS內(nèi)核的活動(dòng)空間。
- 每一個(gè)進(jìn)程都活在自己獨(dú)立的進(jìn)程空間中,0-3G的空間每一個(gè)進(jìn)程是不同的(因?yàn)橛昧颂摂M地址技術(shù)),但是內(nèi)核是唯一的。
?
8、OS下和裸機(jī)下C程序加載執(zhí)行的差異
(1)C語(yǔ)言程序運(yùn)行時(shí)環(huán)境有一定要求
?
- 意思是單獨(dú)個(gè)人寫的C語(yǔ)言程序沒法直接在內(nèi)存中運(yùn)行,需要外部一定的協(xié)助,這段協(xié)助的代碼叫加載運(yùn)行代碼(或者叫構(gòu)建C運(yùn)行時(shí)環(huán)境的代碼,這一段代碼在操作系統(tǒng)下是別人寫好的,會(huì)自動(dòng)添加到我們寫的程序上,這段代碼的主要作用是:給全局變量賦值、清bss段)。
?
(2)ARM裸機(jī)第十六部分,寫shell時(shí)有一次定義了一個(gè)全局變量初始化為0但是實(shí)際不為0,后來(lái)在裸機(jī)的start.S中加了清bss段代碼就變0了。
?
- 這就說(shuō)明在裸機(jī)程序中沒人幫我們來(lái)做這一段加載運(yùn)行時(shí)代碼,要程序員自己做(start.S中的重定位和清bss段就是在做這個(gè)事);
- 在操作系統(tǒng)中運(yùn)行程序時(shí)程序員自己不用操心,會(huì)自動(dòng)完成重定位和清bss,所以我們看到的現(xiàn)象:C語(yǔ)言中未初始化的全局變量默認(rèn)為0。
?
(3)數(shù)據(jù)段的全局變量或靜態(tài)局部變量都是有非0的初值的,這些初值在main函數(shù)運(yùn)行之前就已經(jīng)被初始化了,是重定位期間完成的初始化。
?
?
三、存儲(chǔ)類相關(guān)的關(guān)鍵字
?
?
1、auto
?
- auto關(guān)鍵字在C語(yǔ)言中只有一個(gè)作用,那就是修飾局部變量。
- 平時(shí)定義局部變量時(shí)就是定義的auto的,只是省略了auto關(guān)鍵字而已??梢?#xff0c;auto的局部變量其實(shí)就是默認(rèn)定義的普通的局部變量。
?
2、static
(1)static的第一種用法是:用來(lái)修飾局部變量,形成靜態(tài)局部變量。
?
- 要搞清楚靜態(tài)局部變量和非靜態(tài)局部變量的區(qū)別。本質(zhì)區(qū)別是存儲(chǔ)類不同(存儲(chǔ)類不同就衍生出很多不同)。
- 非靜態(tài)局部變量分配在棧上,而靜態(tài)局部變量分配在數(shù)據(jù)段/bss段上。
?
(2)static的第二種用法是:用來(lái)修飾全局變量,形成靜態(tài)全局變量。
?
- 要搞清楚靜態(tài)全局變量和非靜態(tài)全局變量的區(qū)別。區(qū)別是在鏈接屬性上不同。
?
3、register
(1)register修飾的變量。編譯器會(huì)盡量將它分配在寄存器中(平時(shí)分配的一般的變量都是在內(nèi)存中的)
?
- 分配在寄存器中一樣的用,但是讀寫效率會(huì)高很多。所以register修飾的變量用在那種變量被反復(fù)高頻率的使用,通過改善這個(gè)變量的訪問效率可以極大的提升程序運(yùn)行效率時(shí)。所以register是一種極致提升程序運(yùn)行效率的手段。
?
(2)uboot中用到了一個(gè)register類型的變量gd
?
- 這個(gè)變量是用來(lái)存uboot的全局變量(gd就是global data)。因?yàn)檫@個(gè)全局變量在整個(gè)uboot中到處都被訪問,所以定義成register的。
?
(3)平時(shí)寫代碼要被定義成register這種情況很少,一般慎用。
(4)register編譯器只能承諾盡量將register修飾的變量放在寄存器中,但是不保證一定放在寄存器中。主要原因是因?yàn)榧拇嫫鲾?shù)量有限,不一定有空用。
4、extern
(1)extern主要用來(lái)聲明全局變量,聲明的目的主要是在a.c中定義全局變量而在b.c中使用該變量。
?
- C語(yǔ)言中程序的編譯時(shí)以單個(gè).c源文件為單位的,因此編譯a.c時(shí)只考慮a.c中的內(nèi)容(不會(huì)考了b.c的內(nèi)容),這就導(dǎo)致a.c中使用了b.c中定義的變量時(shí)在編譯時(shí)報(bào)錯(cuò)。解決方案是聲明。
- 應(yīng)該在a.c中使用g_b之前先聲明g_b,聲明就是告訴a.c我在別的文件中定義了g_b,并且它的原型和聲明的一樣,將來(lái)在鏈接的時(shí)候鏈接器會(huì)在別的.o文件中找到這個(gè)同名變量。聲明一個(gè)全局變量就要用到extern關(guān)鍵字
?
5、volatile
(1)C語(yǔ)言中volatile用來(lái)修飾一個(gè)變量,表示這個(gè)變量可以被編譯器之外的東西改變。
?
- 編譯器之內(nèi)的意思是變量的值的改變是代碼的作用,編譯器之外的改變就是這個(gè)改變不是代碼造成的,或者不是當(dāng)前代碼造成的,編譯器在編譯當(dāng)前代碼時(shí)無(wú)法預(yù)知。
- 譬如在中斷處理程序isr中更改了變量的值,譬如多線程中在別的線程更改了這個(gè)變量的值,譬如硬件自動(dòng)更改了這個(gè)變量的值(一般這個(gè)變量是一個(gè)寄存器的值)。
- 中斷isr中引用的變量,多線程中共用的變量,硬件會(huì)更改的變量,三者都是編譯器在編譯時(shí)無(wú)法預(yù)知的更改,此時(shí)應(yīng)用使用volatile告訴編譯器這個(gè)變量屬于這種(可變的、易變的)情況。編譯器在遇到volatile修飾的變量時(shí)就不會(huì)對(duì)改變量的訪問進(jìn)行優(yōu)化,就不會(huì)出現(xiàn)錯(cuò)誤。
?
(2)編譯器的優(yōu)化在一般情況下非常好,可以幫助提升程序效率。但是在特殊情況(volatile)下,變量會(huì)被編譯器想象之外的力量所改變,此時(shí)如果編譯器沒有意識(shí)到而去優(yōu)化則就會(huì)造成優(yōu)化錯(cuò)誤,優(yōu)化錯(cuò)誤就會(huì)帶來(lái)執(zhí)行時(shí)錯(cuò)誤。而且這種錯(cuò)誤很難被發(fā)現(xiàn)。
(3)volatile是程序員意識(shí)到需要volatile然后在定義變量時(shí)加上volatile,如果你遇到了應(yīng)該加volatile的情況而沒有加程序可能會(huì)被錯(cuò)誤的優(yōu)化。如果在不應(yīng)該加volatile而加了的情況程序不會(huì)出錯(cuò)只是會(huì)降低效率。所以我們對(duì)于volatile的態(tài)度應(yīng)該是:正確區(qū)分,該加的時(shí)候加不該加的時(shí)候不加,如果不能確定該不該加為了保險(xiǎn)起見就加上。
6、restrict
(1)c99中才支持的,所以很多延續(xù)c89的編譯器是不支持restrict關(guān)鍵字,gcc支持的。
(2)restrict也是和編譯器行為特征有關(guān)的。
(3)restrict只用來(lái)修飾指針,不能修飾普通變量。
(4)http://blog.chinaunix.net/uid-22197900-id-359209.html
(5)memcpy和memmove的區(qū)別
7、typedef
?
- typedef在C語(yǔ)言關(guān)鍵字歸類上屬于存儲(chǔ)類關(guān)鍵字,但是實(shí)際上和存儲(chǔ)類沒關(guān)系。
?
?
四、作用域詳解
?
1、局部變量的代碼塊作用域
- 代碼塊基本可以理解為一對(duì)大括號(hào){}括起來(lái)的部分。
- 代碼塊不等于函數(shù),因?yàn)閕f ?while for都有{}。所以代碼塊<=函數(shù)。
- 局部變量的作用域是代碼塊作用域,也就是說(shuō)一個(gè)局部變量可以被訪問和使用的范圍僅限于定義這個(gè)局部變量的代碼塊中定義式之后的部分。
?
2、函數(shù)名和全局變量的文件作用域
?
?
- 文件作用域的意思就是全局的訪問權(quán)限,也就是說(shuō)整個(gè).c文件中都可以訪問這些東西。這就是平時(shí)所說(shuō)的局部和全局,全局就是文件作用域。
- 詳細(xì)準(zhǔn)確的說(shuō):函數(shù)和全局變量的作用域是定義所在的整個(gè).c文件之內(nèi)定義式之后的部分。
?
3、注意
?
- 在c89標(biāo)準(zhǔn)的編譯器中(現(xiàn)在很多編譯器還延續(xù)使用c89標(biāo)準(zhǔn)),所有的局部變量必須先定義在最前面,在變量定義之前不能有一句執(zhí)行代碼。
- 在c99標(biāo)準(zhǔn)的編譯器中(gcc兼容c99標(biāo)準(zhǔn))可以允許在代碼塊內(nèi)任意地方定義變量。但是允許定義的變量還是只能使用在定義了之后,定義之前還是不能用的。
?
4、同名變量的掩蔽規(guī)則
?
- 問題:編程時(shí),不可避免會(huì)出現(xiàn)同名變量。變量同名后不一定會(huì)出錯(cuò)。
- 首先,如果兩個(gè)同名變量作用域不同且沒有交疊,這種情況下同名沒有任何影響。
- 其次,如果兩個(gè)同名變量作用域有交疊,C語(yǔ)言規(guī)定在作用域交疊范圍內(nèi),作用域小的一個(gè)變量會(huì)掩蔽掉作用域大的那個(gè)(縣官不如現(xiàn)管)。
?
五、變量的生命周期
1、棧變量的生命周期
- 局部變量(棧變量)存儲(chǔ)在棧上,生命周期是臨時(shí)的。臨時(shí)的意思就是說(shuō):代碼執(zhí)行過程中按照需要去創(chuàng)建、使用、消亡的。
- 譬如一個(gè)函數(shù)內(nèi)定義的局部變量,在這個(gè)函數(shù)每一次被調(diào)用時(shí)都會(huì)創(chuàng)建一次,然后使用,最后在函數(shù)返回的時(shí)候消亡。
- 思考:一個(gè)函數(shù)內(nèi)的局部變量為什么在函數(shù)外不能使用?
- 思考:局部變量為什么分配在棧上?或者說(shuō)局部變量為什么是臨時(shí)生命周期?
?
2、堆變量的生命周期
?
- 首先要明白:堆內(nèi)存空間是客觀存在的,是由操作系統(tǒng)維護(hù)的。我們程序只是去申請(qǐng)然后使用然后釋放。
- 我們只關(guān)心我們程序使用堆內(nèi)存的這一段時(shí)間,因此堆變量也有了自己的生命周期,就是:從malloc申請(qǐng)時(shí)誕生,然后使用,直到free時(shí)消亡。
- 所以堆內(nèi)存在malloc之前和free之后不能再去訪問,因此堆內(nèi)存在實(shí)踐編程時(shí)都是被反復(fù)的malloc和free的。
?
3、數(shù)據(jù)段、bss段變量的生命周期
?
- 全局變量的生命周期是永久的。永久的意思就是在程序被執(zhí)行時(shí)誕生,在程序終止時(shí)消亡。
- 全局變量所占用的內(nèi)存是不能被程序自己釋放的,所以程序如果申請(qǐng)了過多的全局變量會(huì)導(dǎo)致這個(gè)程序一直占用大量?jī)?nèi)存。
?
4、代碼段、只讀段的生命周期
?
- 其實(shí)就是程序執(zhí)行的代碼,其實(shí)就是函數(shù),它的生命周期是永久的。不過一般代碼的生命周期我們并不關(guān)注。
- 有時(shí)候放在代碼段的不只是代碼,還有const類型的常量,還有字符串常量。(const類型的常量、字符串常量有時(shí)候放在rodata段,有時(shí)候放在代碼段,取決于平臺(tái))
?
六、鏈接屬性
?
1、C語(yǔ)言程序的組織架構(gòu):多個(gè)C文件+多個(gè)h文件
- (完整的一個(gè)C語(yǔ)言程序(譬如linux內(nèi)核、uboot)由多個(gè)c文件和多個(gè)h文件組成的。
- 程序的生成過程就是:編譯+鏈接。
- 編譯是為了將函數(shù)/變量等變成.o二進(jìn)制的機(jī)器碼格式,鏈接是為了將各個(gè)獨(dú)立分開的二進(jìn)制的函數(shù)鏈接起來(lái)形成一個(gè)整體的二進(jìn)制可執(zhí)行程序。
2、編譯以文件為單位、鏈接以工程為單位
- 編譯器工作時(shí)是將所有源文件依次讀進(jìn)來(lái),單個(gè)為單位進(jìn)行編譯的。
- 鏈接的時(shí)候?qū)嶋H上是把第一步編譯生成個(gè)單個(gè)的.o文件整體的輸入,然后處理鏈接成一個(gè)可執(zhí)行程序。
3、三種鏈接屬性:外連接、內(nèi)鏈接、無(wú)鏈接
- 外連接的意思就是外部鏈接屬性,也就是說(shuō)這家伙可以在整個(gè)程序范圍內(nèi)(言下之意就是可以跨文件)進(jìn)行鏈接,譬如普通的函數(shù)和全局變量屬于外連接。
- 內(nèi)鏈接的意思就是(c文件內(nèi)部)內(nèi)部鏈接屬性,也就是說(shuō)這家伙可以在當(dāng)前c文件內(nèi)部范圍內(nèi)進(jìn)行鏈接(言下之意就是不能在當(dāng)前c文件外面的其他c文件中進(jìn)行訪問、鏈接)。static修飾的函數(shù)/全局變量屬于內(nèi)鏈接。
- 無(wú)連接的意思就是這個(gè)符號(hào)本身不參與鏈接,它跟鏈接沒關(guān)系。所有的局部變量(auto的、static的)都是無(wú)連接的
4、函數(shù)和全局變量的同名沖突
(1)因?yàn)楹瘮?shù)和全局變量是外部鏈接屬性,就是說(shuō)每一個(gè)函數(shù)和全局變量將來(lái)在整個(gè)程序中所有的c文件都能被訪問,因此在一個(gè)程序中的所有c文件中不能出現(xiàn)同名的函數(shù)/同名的全局變量。
(2)最簡(jiǎn)單的解決方案就是起名字不要重復(fù),但是很難做到。主要原因是一個(gè)很大的工程中函數(shù)和全局變量名字太多了,而且一個(gè)大工程不是一個(gè)人完成的,是很多人協(xié)作完成,所以很難保證不會(huì)重名。解決方案呢?
(3)現(xiàn)代高級(jí)語(yǔ)言中完美解決這個(gè)問題的方法是命名空間namespace(其實(shí)就是給一個(gè)變量帶上各個(gè)級(jí)別的前綴)。但是C語(yǔ)言不是這么解決的。
?
- C語(yǔ)言比較早碰到這個(gè)問題,當(dāng)時(shí)還沒發(fā)明namespace概念,當(dāng)時(shí)C語(yǔ)言就發(fā)明了一種不是很完美但是湊活能用的解決方案,就是三種鏈接屬性的方法。
- C語(yǔ)言的鏈接屬性解決重名問題思路是這樣的:我們將明顯不會(huì)在其他c文件中引用(只在當(dāng)前c文件中引用)的函數(shù)/全局變量,使用static修飾使其成為內(nèi)鏈接屬性,這樣在將來(lái)連接時(shí)即使2個(gè)c文件中有重名的函數(shù)/全局變量,只要其中一個(gè)或2個(gè)為內(nèi)鏈接屬性就沒事。
- 這種解決方案在一定程度上解決了問題。但是沒有從根本上解決問題,留下了很多麻煩。所以這個(gè)就導(dǎo)致了C語(yǔ)言寫很大型的項(xiàng)目難度很大。
?
5、static的第二種用法:修飾全局變量和函數(shù)
- 普通的(非靜態(tài))的函數(shù)/全局變量,默認(rèn)的鏈接屬性是外部的;
- static(靜態(tài))的函數(shù)/全局變量,鏈接屬性是內(nèi)部鏈接。
?
七、總結(jié)
1、普通(自動(dòng))局部變量分配在棧上,作用域?yàn)榇a塊作用域,生命周期是臨時(shí),連接屬性為無(wú)連接。定義時(shí)如果未顯式初始化則其值隨機(jī),變量地址由運(yùn)行時(shí)在棧上分配得到,多次執(zhí)行時(shí)地址不一定相同,函數(shù)不能返回該類變量的地址(指針)作為返回值。
2、靜態(tài)局部變量分配在數(shù)據(jù)段/bss段(顯式初始化為非0則在數(shù)據(jù)段,顯式初始化為0或未顯示初始化則在bss段),作用域?yàn)榇a塊作用域(人為規(guī)定的),生命周期為永久(天然的),鏈接屬性為無(wú)連接(天然的)。定義時(shí)如果未顯式初始化則其值為0(天然的),變量地址由運(yùn)行時(shí)環(huán)境在加載程序時(shí)確定,整個(gè)程序運(yùn)行過程中唯一不變;靜態(tài)局部變量其實(shí)就是作用域?yàn)榇a塊作用域(同時(shí)鏈接屬性為無(wú)連接)的全局變量。靜態(tài)局部變量可以改為用全局變量實(shí)現(xiàn)(程序中盡量避免用全局變量,因?yàn)闀?huì)破壞結(jié)構(gòu)性)。
3、靜態(tài)全局變量/靜態(tài)函數(shù)和普通全局變量/普通函數(shù)的唯一差別是:static使全局變量/函數(shù)的鏈接屬性由外部鏈接(整個(gè)程序所有文件范圍)轉(zhuǎn)為內(nèi)部鏈接(當(dāng)前c文件內(nèi))。這是為了解決全局變量/函數(shù)的重名問題(C語(yǔ)言沒有命名空間namespace的概念,因此在程序中文件變多之后全局變量/函數(shù)的重名問題非常嚴(yán)重,將不必要被其他文件引用的全局變量/函數(shù)聲明為static可以很大程度上改善重名問題,但是仍未徹底解決)。
4、寫程序盡量避免使用全局變量,尤其是非static類型的全局變量。能確定不會(huì)被其他文件引用的全局變量一定要static修飾。
5、注意區(qū)分全局變量的定義和聲明。一般規(guī)律如下:如果定義的同時(shí)有初始化則一定會(huì)被認(rèn)為是定義;如果只是定義而沒有初始化則有可能被編譯器認(rèn)為是定義,也可能被認(rèn)為是聲明,要具體分析;如果使用extern則肯定會(huì)被認(rèn)為是聲明(實(shí)際上使用extern也可以有定義,實(shí)際上加extern就是明確聲明這個(gè)變量為外部鏈接屬性)。
6、全局變量應(yīng)該定義在c文件中并且在頭文件中聲明,而不要定義在頭文件中(因?yàn)槿绻x在頭文件中,則該頭文件被多個(gè)c文件包含時(shí)該全局變量會(huì)重復(fù)定義)。
7、在b.c中引用a.c中定義的全局變量/函數(shù)有2種方法:一是在a.h中聲明該函數(shù)/全局變量,然后在b.c中#include <a.h>;二是在b.c中使用extern顯式聲明要引用的函數(shù)/全局變量。其中第一種方法比較正式。
8、存儲(chǔ)類決定生命周期,作用域決定鏈接屬性。
9、宏和inline函數(shù)的鏈接屬性為無(wú)連接。
總結(jié)
以上是生活随笔為你收集整理的存储类、作用域、生命周期、链接属性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FileZilla客户端使用遇到的问题
- 下一篇: u-boot启动参数命令格式