0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【知識(shí)科普】C語言的static究竟限制了誰

RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 來源:未知 ? 2023-08-02 20:05 ? 次閱讀

【知識(shí)科普C語言的static究竟限制了誰?

這是一個(gè)有趣的話題,雖然說教科書給了你一些說法,但你真正能把static說清楚嗎?本文將通過一個(gè)案例,給大家做一個(gè)深度的拆解分析。

注:在本文的討論中,無明確說明時(shí),指的都是static修飾函數(shù),而非變量。

1 問題來源


最近的幾個(gè)月一直在維護(hù)我的個(gè)人專屬【嵌入式技術(shù)交流群】,平時(shí)大家都很積極在群里討論技術(shù)問題。

就在上個(gè)星期,在群里收到一個(gè)有關(guān)static的討論,我個(gè)人覺得挺有意思的,于是打算將其整理成文,希望能夠幫助大家更好地理解和應(yīng)用static這個(gè)關(guān)鍵字。

群里的原問題如下:

大佬們,問一個(gè)比較低智問題,static修飾的變量不是只能被當(dāng)前文件所調(diào)用嗎?為什么這里在其他.c文件可以調(diào)用get_board_led_opr這個(gè)函數(shù)獲取board_demo_led_opr這個(gè)變量的值。

03b5a3c4-312c-11ee-9e74-dac502259ad0.png

2 關(guān)于上述問題的答疑


這個(gè)問題群里也給出了一些參考答案,而我一開始的回答,并沒有直接回答答案,而是隨手提出了3個(gè)問題:

問自己幾個(gè)問題:

1.get函數(shù)返回什么地址(各種地址)語法上有約束條款嗎?

2.static修飾的全局變量存放在哪里?它的地址是什么樣的?

3.c語言里面要想訪問任意一個(gè)地址,從語法層面上,能阻止得了嗎?

提問者的回答:

(1)get_board_led_opr函數(shù)返回的是一個(gè)自定義的結(jié)構(gòu)體get_board_led_opr。但是get_board_led_opr這個(gè)結(jié)構(gòu)體被static修飾了。(2)get_board_led_opr結(jié)構(gòu)體放在了board_demo.c中,而調(diào)用get_board_led_opr函數(shù)是在leddrv.c中。
(3)我詢問了另外一個(gè)群里面的大佬,他們說,static僅僅在編譯期間有用。在運(yùn)行狀態(tài)是無效果的。也就是說,雖然leddrv.c無法直接使用get_board_led_opr這個(gè)結(jié)構(gòu)體。但是可以利用get_board_led_opr函數(shù),間接的獲取get_board_led_opr這個(gè)結(jié)構(gòu)體,因?yàn)間et_board_led_opr函數(shù)和et_board_led_opr這個(gè)結(jié)構(gòu)體在同一個(gè).c文件中
上述問題的點(diǎn)關(guān)鍵在于理解兩個(gè):
  • 被static修飾之后,這個(gè)變量變成了什么?
  • C語言的萬能指針。
??首先,被static修飾之后,意味著只有 當(dāng)前的C語言C文件 可以直接 引用訪問它,但是并不代表外部的模塊(除當(dāng)前C文件外的其他C文件)就不能訪問它。直接訪問肯定是不行的,但是 間接 的方式肯定是可以的。它的方法就是如上圖的代碼片段那樣,將static變量的地址,以指針的形式傳出去給其他模塊即可。這里還要理解的一點(diǎn)是,被static修飾的變量是存放在全局的數(shù)據(jù)區(qū),它的有效生存空間是整一個(gè)C工程運(yùn)行時(shí)間內(nèi)都是有效的。所以你通過指針去訪問它,就變成了可能;這也是我們學(xué)習(xí)指針時(shí),提到的 間接訪問 的最真實(shí)體驗(yàn)。

3 教科書里的static


乘此機(jī)會(huì),我們來復(fù)習(xí)一下C語言教科書,對于static關(guān)鍵字,它們是怎么描述的?由于手頭標(biāo)準(zhǔn)的教科書,已很難找了,索性問一下ChatGPT,看看它的總結(jié):

在C語言中,static關(guān)鍵字有兩種主要的用法:靜態(tài)變量和靜態(tài)函數(shù)。

1. 靜態(tài)變量:

靜態(tài)變量是在程序運(yùn)行期間一直存在的變量,其生命周期從聲明處到程序結(jié)束。靜態(tài)變量被存儲(chǔ)在靜態(tài)數(shù)據(jù)區(qū),不會(huì)受到函數(shù)的調(diào)用和返回的影響,每次進(jìn)入函數(shù)都會(huì)保留上一次的值。靜態(tài)變量可以在函數(shù)內(nèi)部或者全局作用域中聲明。在函數(shù)內(nèi)部聲明的靜態(tài)變量只能在該函數(shù)內(nèi)部訪問,而在全局作用域中聲明的靜態(tài)變量可以在整個(gè)文件中訪問。靜態(tài)變量的主要作用:- 維護(hù)變量的持久狀態(tài),保持值的連續(xù)性。- 限制變量的作用域,只能在函數(shù)內(nèi)或者文件內(nèi)訪問。- 避免與同名的全局變量產(chǎn)生沖突。示例代碼:

void func()

{

static int count = 0; // 定義一個(gè)靜態(tài)變量

count++;

printf(“Count: %d ”, count);

}

int main()

{

func(); // 輸出:Count: 1

func(); // 輸出:Count: 2

func(); // 輸出:Count: 3

return 0;

}

2. 靜態(tài)函數(shù):

靜態(tài)函數(shù)是只能在當(dāng)前源文件中使用的函數(shù),其作用于只限于聲明所在的文件,無法被其他文件調(diào)用。使用static關(guān)鍵字修飾函數(shù),可以實(shí)現(xiàn)函數(shù)的隱藏和封裝。因此,靜態(tài)函數(shù)的主要作用是限制函數(shù)的作用域,防止其他文件訪問該函數(shù),避免命名沖突,并且提高代碼的可讀性和可維護(hù)性。示例代碼:

static void util_func(int value)

{

printf(“Value: %d ”, value);

}

int main()

{

util_func(10); // 可以在當(dāng)前文件中調(diào)用util_func函數(shù)

return 0;

}

總結(jié):static關(guān)鍵字在C語言中的用法主要有靜態(tài)變量和靜態(tài)函數(shù)。靜態(tài)變量用于維護(hù)變量的持久狀態(tài)和限制作用域,靜態(tài)函數(shù)用于限制函數(shù)的作用域和提高代碼的可讀性。

基本從ChatGPT的總結(jié),可以了解清楚static的使用;不過它上面未提及到的一點(diǎn)是:

在static修飾的靜態(tài)變量中,有兩種情況,一種是修飾全局的變量,叫靜態(tài)全局變量;另一種是修飾局部變量,叫靜態(tài)局部變量(其實(shí)如果從作用周期的時(shí)間來看,它也是全局的)。ChatGPT中演示的靜態(tài)局部變量,它的作用域就僅限于定義變量的這個(gè)函數(shù)內(nèi)(準(zhǔn)確說是,定義變量的大括號范圍內(nèi));一旦出了這個(gè)作用域,是沒有辦法訪問到的。而靜態(tài)全局變量,它的作用域又比靜態(tài)局部變量更寬泛些,它可以允許定義靜態(tài)全局變量的整個(gè)C文件內(nèi),都可以訪問它;但是之外的,其他C文件是無法訪問的。綜上,static關(guān)鍵字,主要強(qiáng)調(diào)的是 靜態(tài)的 這個(gè)含義,無非就是作用域的大小問題。 4 C語言的static究竟限制了誰?
從編譯原理和編譯流程來拆解這個(gè),問題的答案就很快就能出來。我們就以第3小節(jié)中,ChatGPT給出的示例代碼為例,深度拆解一下這個(gè)static。在正式拆解之前,需要具備一些前置知識(shí):C語言的編譯流程。曾經(jīng),我寫過一篇相關(guān)的文章,大家可以提前參考下,一文帶你了解C代碼到底是如何被編譯的在這里,我不打算一一搬過來,僅僅把一張圖貼過來參考:

0480074a-312c-11ee-9e74-dac502259ad0.png

我們順著這個(gè)思路來拆解跟蹤一下代碼里面的 static。

  • 編寫C代碼(C源代碼里面的static)


		

1main.c 2#include 3staticintg_count=0; 4voidfunc() 5{ 6staticintl_count=0;//定義一個(gè)靜態(tài)局部變量 7l_count++; 8g_count++; 9printf("l_count:%d,g_count:%d ",l_count,g_count); 10} 11staticvoidutil_func(intvalue)//定義一個(gè)靜態(tài)函數(shù) 12{ 13printf("Value:%d ",value); 14} 15externvoidtest_func(void); 16intmain() 17{ 18func();//輸出:l_count:1 19func();//輸出:l_count:2 20func();//輸出:l_count:3 21util_func(10);//可以在當(dāng)前文件中調(diào)用util_func函數(shù),輸出:Value: 10 22test_func();//調(diào)用test.c中的函數(shù) 23return0; 24}


		1test.c  2//假設(shè)它們都是可以訪問的  3externintl_count;  4externintg_count;  5externvoidutil_func(intvalue);  6voidtest_func(void)  7{  8#if0  9l_count++;//訪問l_count靜態(tài)局部變量,編譯報(bào)錯(cuò) 10g_count++;//訪問g_count靜態(tài)全局變量,編譯報(bào)錯(cuò) 11util_func(100);//調(diào)用main.c中的static函數(shù),編譯報(bào)錯(cuò) 12#endif 13}

當(dāng)test_func中的if-0打開后,根據(jù)我們上面的理論分析,肯定是編譯不過的,如下:


		1test_static$gcc-otest*.c 2/usr/bin/ld:/tmp/ccawkyDR.o:infunction`test_func': 3test.c:(.text+0xa):undefinedreferenceto`l_count' 4/usr/bin/ld:test.c:(.text+0x13):undefinedreferenceto`l_count' 5/usr/bin/ld:test.c:(.text+0x19):undefinedreferenceto`g_count' 6/usr/bin/ld:test.c:(.text+0x22):undefinedreferenceto`g_count' 7/usr/bin/ld:test.c:(.text+0x2c):undefinedreferenceto`util_func' 8collect2:error:ldreturned1exitstatus

像這種就是很明顯的找不到變量或函數(shù)的實(shí)現(xiàn)體,從而出現(xiàn)找不到引用的 鏈接 錯(cuò)誤。

去掉這些引用后(if-0)打開,即可編譯成功,且能夠正常運(yùn)行。


		

1test_static$gcc-otest*.c 2test_static$./test 3l_count:1,g_count:1 4l_count:2,g_count:2 5l_count:3,g_count:3 6Value:10

  • 分步拆解1:先看預(yù)處理后static的情況

使用的命令下:gcc -c -o main.o main.c -save-temps=obj

這時(shí)候我們可以看到 main.i main.s main.o 這幾個(gè)文件。

先看main.i 的內(nèi)容:


		1忽略前面對頭文件內(nèi)容的搬運(yùn)  2#873"/usr/include/stdio.h"34  3#2"main.c"2  4#3"main.c"  5staticintg_count=0;  6voidfunc()  7{  8staticintl_count=0;  9l_count++; 10g_count++; 11printf("l_count:%d,g_count:%d ",l_count,g_count); 12} 13staticvoidutil_func(intvalue) 14{ 15printf("Value:%d ",value); 16} 17externvoidtest_func(void); 18intmain() 19{ 20func(); 21func(); 22func(); 23util_func(10); 24test_func(); 25return0;

從上基本可以看到,static還是在的,并且整一個(gè)預(yù)處理后的代碼,基本保留了源代碼的樣子(原因是我們并沒有使用類似宏定義的內(nèi)容)。

  • 拆解第2步:看看匯編文件有沒有static的影子

這時(shí)候我們要查看的是 main.s 文件:


		1test_static$catmain.s  2.file"main.c"  3.text  4.localg_count  5.commg_count,4,4  6.section.rodata  7.LC0:  8.string"l_count:%d,g_count:%d "  9.text  10.globlfunc  11.typefunc,@function  12func:  13.LFB0:  14.cfi_startproc  15endbr64  16pushq%rbp  17.cfi_def_cfa_offset16  18.cfi_offset6,-16  19movq%rsp,%rbp  20.cfi_def_cfa_register6  21movll_count.2316(%rip),%eax  22addl$1,%eax  23movl%eax,l_count.2316(%rip)  24movlg_count(%rip),%eax  25addl$1,%eax  26movl%eax,g_count(%rip)  27movlg_count(%rip),%edx  28movll_count.2316(%rip),%eax  29movl%eax,%esi  30leaq.LC0(%rip),%rdi  31movl$0,%eax  32callprintf@PLT  33nop  34popq%rbp  35.cfi_def_cfa7,8  36ret  37.cfi_endproc  38.LFE0:  39.sizefunc,.-func  40.section.rodata  41.LC1:  42.string"Value:%d "  43.text  44.typeutil_func,@function  45util_func:  46.LFB1:  47.cfi_startproc  48endbr64  49pushq%rbp  50.cfi_def_cfa_offset16  51.cfi_offset6,-16  52movq%rsp,%rbp  53.cfi_def_cfa_register6  54subq$16,%rsp  55movl%edi,-4(%rbp)  56movl-4(%rbp),%eax  57movl%eax,%esi  58leaq.LC1(%rip),%rdi  59movl$0,%eax  60callprintf@PLT  61nop  62leave  63.cfi_def_cfa7,8  64ret  65.cfi_endproc  66.LFE1:  67.sizeutil_func,.-util_func  68.globlmain  69.typemain,@function  70main:  71.LFB2:  72.cfi_startproc  73endbr64  74pushq%rbp  75.cfi_def_cfa_offset16  76.cfi_offset6,-16  77movq%rsp,%rbp  78.cfi_def_cfa_register6  79movl$0,%eax  80callfunc  81movl$0,%eax  82callfunc  83movl$0,%eax  84callfunc  85movl$10,%edi  86callutil_func  87calltest_func@PLT  88movl$0,%eax  89popq%rbp  90.cfi_def_cfa7,8  91ret  92.cfi_endproc  93.LFE2:  94.sizemain,.-main  95.locall_count.2316  96.comml_count.2316,4,4  97.ident"GCC:(Ubuntu9.4.0-1ubuntu1~20.04.1)9.4.0"  98.section.note.GNU-stack,"",@progbits  99.section.note.gnu.property,"a" 100.align8 101.long1f-0f 102.long4f-1f 103.long5 1040: 105.string"GNU" 1061: 107.align8 108.long0xc0000002 109.long3f-2f 1102: 111.long0x3 1123: 113.align8 1144:

初一打開,可能有種不太認(rèn)識(shí)的感覺,沒關(guān)系,我們先找到我們能認(rèn)識(shí)的東西。

先找到被static修飾過的內(nèi)容(靜態(tài)全局變量、靜態(tài)局部變量、靜態(tài)函數(shù))。

1)靜態(tài)全局變量g_count:


		

1.file"main.c" 2.text 3.localg_count 4.commg_count,4,4 5.section.rodata

2)靜態(tài)局部變量l_count:


		1.LFE2: 2.sizemain,.-main 3.locall_count.2316 4.comml_count.2316,4,4

3)靜態(tài)函數(shù)util_func:


		1.string"Value:%d "  2.text  3.typeutil_func,@function  4util_func:  5.LFB1:  6.cfi_startproc  7endbr64  8pushq%rbp  9.cfi_def_cfa_offset16 10.cfi_offset6,-16 11movq%rsp,%rbp 12.cfi_def_cfa_register6 13subq$16,%rsp 14movl%edi,-4(%rbp) 15movl-4(%rbp),%eax 16movl%eax,%esi 17leaq.LC1(%rip),%rdi 18movl$0,%eax 19callprintf@PLT 20nop 21leave 22.cfi_def_cfa7,8 23ret 24.cfi_endproc

由于我們只是對main.c進(jìn)行匯編,所以看不出全貌,但是能夠確認(rèn)的是,在匯編文件中,static已經(jīng)消失了,換句話說,接下來就沒static啥事情了,而是轉(zhuǎn)為其他信息了。我們接著往下拆解。

  • 拆解第3步:obj文件里面確認(rèn)沒有static的要素嗎?

我們看下main.o文件,由于它不是可讀文件,所以得用其他指令分析下:


		

1test_static$readelf-amain.o 2ELFHeader: 3Magic:7f454c46020101000000000000000000 4Class:ELF64 5Data:2'scomplement,littleendian 6Version:1(current) 7OS/ABI:UNIX-SystemV 8ABIVersion:0 9Type:REL(Relocatablefile) 10Machine:AdvancedMicroDevicesX86-64 11Version:0x1 12Entrypointaddress:0x0 13Startofprogramheaders:0(bytesintofile) 14Startofsectionheaders:1520(bytesintofile) 15Flags:0x0 16Sizeofthisheader:64(bytes) 17Sizeofprogramheaders:0(bytes) 18Numberofprogramheaders:0 19Sizeofsectionheaders:64(bytes) 20Numberofsectionheaders:14 21Sectionheaderstringtableindex:13 22SectionHeaders: 23[Nr]NameTypeAddressOffset 24SizeEntSizeFlagsLinkInfoAlign 25[0]NULL000000000000000000000000 2600000000000000000000000000000000000 27[1].textPROGBITS000000000000000000000040 2800000000000000ac0000000000000000AX001 29[2].rela.textRELA0000000000000000000003e0 3000000000000001500000000000000018I1118 31[3].dataPROGBITS0000000000000000000000ec 3200000000000000000000000000000000WA001 33[4].bssNOBITS0000000000000000000000ec 3400000000000000080000000000000000WA004 35[5].rodataPROGBITS0000000000000000000000ec 3600000000000000250000000000000000A001 37[6].commentPROGBITS000000000000000000000111 38000000000000002c0000000000000001MS001 39[7].note.GNU-stackPROGBITS00000000000000000000013d 4000000000000000000000000000000000001 41[8].note.gnu.propertNOTE000000000000000000000140 4200000000000000200000000000000000A008 43[9].eh_framePROGBITS000000000000000000000160 4400000000000000780000000000000000A008 45[10].rela.eh_frameRELA000000000000000000000530 4600000000000000480000000000000018I1198 47[11].symtabSYMTAB0000000000000000000001d8 4800000000000001b0000000000000001812138 49[12].strtabSTRTAB000000000000000000000388 5000000000000000530000000000000000001 51[13].shstrtabSTRTAB000000000000000000000578 5200000000000000740000000000000000001 53KeytoFlags: 54W(write),A(alloc),X(execute),M(merge),S(strings),I(info), 55L(linkorder),O(extraOSprocessingrequired),G(group),T(TLS), 56C(compressed),x(unknown),o(OSspecific),E(exclude), 57l(large),p(processorspecific) 58Therearenosectiongroupsinthisfile. 59Therearenoprogramheadersinthisfile. 60Thereisnodynamicsectioninthisfile. 61Relocationsection'.rela.text'atoffset0x3e0contains14entries: 62OffsetInfoTypeSym.ValueSym.Name+Addend 6300000000000a000400000002R_X86_64_PC320000000000000000.bss+0 64000000000013000400000002R_X86_64_PC320000000000000000.bss+0 65000000000019000400000002R_X86_64_PC320000000000000000.bss-4 66000000000022000400000002R_X86_64_PC320000000000000000.bss-4 67000000000028000400000002R_X86_64_PC320000000000000000.bss-4 6800000000002e000400000002R_X86_64_PC320000000000000000.bss+0 69000000000037000600000002R_X86_64_PC320000000000000000.rodata-4 70000000000041000f00000004R_X86_64_PLT320000000000000000printf-4 7100000000005f000600000002R_X86_64_PC320000000000000000.rodata+16 72000000000069000f00000004R_X86_64_PLT320000000000000000printf-4 7300000000007e000d00000004R_X86_64_PLT320000000000000000func-4 74000000000088000d00000004R_X86_64_PLT320000000000000000func-4 75000000000092000d00000004R_X86_64_PLT320000000000000000func-4 760000000000a1001100000004R_X86_64_PLT320000000000000000test_func-4 77Relocationsection'.rela.eh_frame'atoffset0x530contains3entries: 78OffsetInfoTypeSym.ValueSym.Name+Addend 79000000000020000200000002R_X86_64_PC320000000000000000.text+0 80000000000040000200000002R_X86_64_PC320000000000000000.text+48 81000000000060000200000002R_X86_64_PC320000000000000000.text+70 82ThedecodingofunwindsectionsformachinetypeAdvancedMicroDevicesX86-64isnotcurrentlysupported. 83Symboltable'.symtab'contains18entries: 84Num:ValueSizeTypeBindVisNdxName 850:00000000000000000NOTYPELOCALDEFAULTUND 861:00000000000000000FILELOCALDEFAULTABSmain.c 872:00000000000000000SECTIONLOCALDEFAULT1 883:00000000000000000SECTIONLOCALDEFAULT3 894:00000000000000000SECTIONLOCALDEFAULT4 905:00000000000000004OBJECTLOCALDEFAULT4g_count 916:00000000000000000SECTIONLOCALDEFAULT5 927:00000000000000044OBJECTLOCALDEFAULT4l_count.2316 938:000000000000004840FUNCLOCALDEFAULT1util_func 949:00000000000000000SECTIONLOCALDEFAULT7 9510:00000000000000000SECTIONLOCALDEFAULT8 9611:00000000000000000SECTIONLOCALDEFAULT9 9712:00000000000000000SECTIONLOCALDEFAULT6 9813:000000000000000072FUNCGLOBALDEFAULT1func 9914:00000000000000000NOTYPEGLOBALDEFAULTUND_GLOBAL_OFFSET_TABLE_ 10015:00000000000000000NOTYPEGLOBALDEFAULTUNDprintf 10116:000000000000007060FUNCGLOBALDEFAULT1main 10217:00000000000000000NOTYPEGLOBALDEFAULTUNDtest_func 103Noversioninformationfoundinthisfile. 104Displayingnotesfoundin:.note.gnu.property 105OwnerDatasizeDescription 106GNU0x00000010NT_GNU_PROPERTY_TYPE_0 107Properties:x86feature:IBT,SHSTK 108recan@ubuntu:~/win_share_workspace/test_share/test_static$

從上面可以看到,g_count、l_count、util_func 都被 LOCAL 修飾了,而非 GLOBAL 的:

		15:00000000000000004OBJECTLOCALDEFAULT4g_count 26:00000000000000000SECTIONLOCALDEFAULT5 37:00000000000000044OBJECTLOCALDEFAULT4l_count.2316 48:000000000000004840FUNCLOCALDEFAULT1util_func 

究竟這兩者修飾有啥區(qū)別,會(huì)產(chǎn)生什么影響呢?我們接著往下拆解。

  • 拆解第4步:鏈接后的可執(zhí)行文件反匯編

前面也說到了,由于我們都只看到 main這個(gè)C文件相關(guān) 預(yù)處理、匯編、obj內(nèi)容,而沒有看到整個(gè)可執(zhí)行文件的全貌。

執(zhí)行反匯編看看:


		1test_static$objdump-l-d-x-s-Stest  2test:fileformatelf64-x86-64  3test  4architecture:i386:x86-64,flags0x00000150:  5HAS_SYMS,DYNAMIC,D_PAGED  6startaddress0x0000000000001060  7ProgramHeader:  8PHDRoff0x0000000000000040vaddr0x0000000000000040paddr0x0000000000000040align2**3  9filesz0x00000000000002d8memsz0x00000000000002d8flagsr--  10INTERPoff0x0000000000000318vaddr0x0000000000000318paddr0x0000000000000318align2**0  11filesz0x000000000000001cmemsz0x000000000000001cflagsr--  12LOADoff0x0000000000000000vaddr0x0000000000000000paddr0x0000000000000000align2**12  13filesz0x0000000000000600memsz0x0000000000000600flagsr--  14LOADoff0x0000000000001000vaddr0x0000000000001000paddr0x0000000000001000align2**12  15filesz0x0000000000000285memsz0x0000000000000285flagsr-x  16LOADoff0x0000000000002000vaddr0x0000000000002000paddr0x0000000000002000align2**12  17filesz0x00000000000001f0memsz0x00000000000001f0flagsr--  18LOADoff0x0000000000002db8vaddr0x0000000000003db8paddr0x0000000000003db8align2**12  19filesz0x0000000000000258memsz0x0000000000000268flagsrw-  20DYNAMICoff0x0000000000002dc8vaddr0x0000000000003dc8paddr0x0000000000003dc8align2**3  21filesz0x00000000000001f0memsz0x00000000000001f0flagsrw-  22NOTEoff0x0000000000000338vaddr0x0000000000000338paddr0x0000000000000338align2**3  23filesz0x0000000000000020memsz0x0000000000000020flagsr--  24NOTEoff0x0000000000000358vaddr0x0000000000000358paddr0x0000000000000358align2**2  25filesz0x0000000000000044memsz0x0000000000000044flagsr--  260x6474e553off0x0000000000000338vaddr0x0000000000000338paddr0x0000000000000338align2**3  27filesz0x0000000000000020memsz0x0000000000000020flagsr--  28EH_FRAMEoff0x000000000000202cvaddr0x000000000000202cpaddr0x000000000000202calign2**2  29filesz0x000000000000005cmemsz0x000000000000005cflagsr--  30STACKoff0x0000000000000000vaddr0x0000000000000000paddr0x0000000000000000align2**4  31filesz0x0000000000000000memsz0x0000000000000000flagsrw-  32RELROoff0x0000000000002db8vaddr0x0000000000003db8paddr0x0000000000003db8align2**0  33filesz0x0000000000000248memsz0x0000000000000248flagsr--  34DynamicSection:  35NEEDEDlibc.so.6  36INIT0x0000000000001000  37FINI0x0000000000001278  38INIT_ARRAY0x0000000000003db8  39INIT_ARRAYSZ0x0000000000000008  40FINI_ARRAY0x0000000000003dc0  41FINI_ARRAYSZ0x0000000000000008  42GNU_HASH0x00000000000003a0  43STRTAB0x0000000000000470  44SYMTAB0x00000000000003c8  45STRSZ0x0000000000000084  46SYMENT0x0000000000000018  47DEBUG0x0000000000000000  48PLTGOT0x0000000000003fb8  49PLTRELSZ0x0000000000000018  50PLTREL0x0000000000000007  51JMPREL0x00000000000005e8  52RELA0x0000000000000528  53RELASZ0x00000000000000c0  54RELAENT0x0000000000000018  55FLAGS0x0000000000000008  56FLAGS_10x0000000008000001  57VERNEED0x0000000000000508  58VERNEEDNUM0x0000000000000001  59VERSYM0x00000000000004f4  60RELACOUNT0x0000000000000003  61VersionReferences:  62requiredfromlibc.so.6:  630x09691a750x0002GLIBC_2.2.5  64Sections:  65IdxNameSizeVMALMAFileoffAlgn  660.interp0000001c00000000000003180000000000000318000003182**0  67CONTENTS,ALLOC,LOAD,READONLY,DATA  681.note.gnu.property0000002000000000000003380000000000000338000003382**3  69CONTENTS,ALLOC,LOAD,READONLY,DATA  702.note.gnu.build-id0000002400000000000003580000000000000358000003582**2  71CONTENTS,ALLOC,LOAD,READONLY,DATA  723.note.ABI-tag00000020000000000000037c000000000000037c0000037c2**2  73CONTENTS,ALLOC,LOAD,READONLY,DATA  744.gnu.hash0000002400000000000003a000000000000003a0000003a02**3  75CONTENTS,ALLOC,LOAD,READONLY,DATA  765.dynsym000000a800000000000003c800000000000003c8000003c82**3  77CONTENTS,ALLOC,LOAD,READONLY,DATA  786.dynstr0000008400000000000004700000000000000470000004702**0  79CONTENTS,ALLOC,LOAD,READONLY,DATA  807.gnu.version0000000e00000000000004f400000000000004f4000004f42**1  81CONTENTS,ALLOC,LOAD,READONLY,DATA  828.gnu.version_r0000002000000000000005080000000000000508000005082**3  83CONTENTS,ALLOC,LOAD,READONLY,DATA  849.rela.dyn000000c000000000000005280000000000000528000005282**3  85CONTENTS,ALLOC,LOAD,READONLY,DATA  8610.rela.plt0000001800000000000005e800000000000005e8000005e82**3  87CONTENTS,ALLOC,LOAD,READONLY,DATA  8811.init0000001b00000000000010000000000000001000000010002**2  89CONTENTS,ALLOC,LOAD,READONLY,CODE  9012.plt0000002000000000000010200000000000001020000010202**4  91CONTENTS,ALLOC,LOAD,READONLY,CODE  9213.plt.got0000001000000000000010400000000000001040000010402**4  93CONTENTS,ALLOC,LOAD,READONLY,CODE  9414.plt.sec0000001000000000000010500000000000001050000010502**4  95CONTENTS,ALLOC,LOAD,READONLY,CODE  9615.text0000021500000000000010600000000000001060000010602**4  97CONTENTS,ALLOC,LOAD,READONLY,CODE  9816.fini0000000d00000000000012780000000000001278000012782**2  99CONTENTS,ALLOC,LOAD,READONLY,CODE 10017.rodata0000002900000000000020000000000000002000000020002**2 101CONTENTS,ALLOC,LOAD,READONLY,DATA 10218.eh_frame_hdr0000005c000000000000202c000000000000202c0000202c2**2 103CONTENTS,ALLOC,LOAD,READONLY,DATA 10419.eh_frame0000016800000000000020880000000000002088000020882**3 105CONTENTS,ALLOC,LOAD,READONLY,DATA 10620.init_array000000080000000000003db80000000000003db800002db82**3 107CONTENTS,ALLOC,LOAD,DATA 10821.fini_array000000080000000000003dc00000000000003dc000002dc02**3 109CONTENTS,ALLOC,LOAD,DATA 11022.dynamic000001f00000000000003dc80000000000003dc800002dc82**3 111CONTENTS,ALLOC,LOAD,DATA 11223.got000000480000000000003fb80000000000003fb800002fb82**3 113CONTENTS,ALLOC,LOAD,DATA 11424.data0000001000000000000040000000000000004000000030002**3 115CONTENTS,ALLOC,LOAD,DATA 11625.bss0000001000000000000040100000000000004010000030102**2 117ALLOC 11826.comment0000002b00000000000000000000000000000000000030102**0 119CONTENTS,READONLY 120SYMBOLTABLE: 1210000000000000318ld.interp0000000000000000.interp 1220000000000000338ld.note.gnu.property0000000000000000.note.gnu.property 1230000000000000358ld.note.gnu.build-id0000000000000000.note.gnu.build-id 124000000000000037cld.note.ABI-tag0000000000000000.note.ABI-tag 12500000000000003a0ld.gnu.hash0000000000000000.gnu.hash 12600000000000003c8ld.dynsym0000000000000000.dynsym 1270000000000000470ld.dynstr0000000000000000.dynstr 12800000000000004f4ld.gnu.version0000000000000000.gnu.version 1290000000000000508ld.gnu.version_r0000000000000000.gnu.version_r 1300000000000000528ld.rela.dyn0000000000000000.rela.dyn 13100000000000005e8ld.rela.plt0000000000000000.rela.plt 1320000000000001000ld.init0000000000000000.init 1330000000000001020ld.plt0000000000000000.plt 1340000000000001040ld.plt.got0000000000000000.plt.got 1350000000000001050ld.plt.sec0000000000000000.plt.sec 1360000000000001060ld.text0000000000000000.text 1370000000000001278ld.fini0000000000000000.fini 1380000000000002000ld.rodata0000000000000000.rodata 139000000000000202cld.eh_frame_hdr0000000000000000.eh_frame_hdr 1400000000000002088ld.eh_frame0000000000000000.eh_frame 1410000000000003db8ld.init_array0000000000000000.init_array 1420000000000003dc0ld.fini_array0000000000000000.fini_array 1430000000000003dc8ld.dynamic0000000000000000.dynamic 1440000000000003fb8ld.got0000000000000000.got 1450000000000004000ld.data0000000000000000.data 1460000000000004010ld.bss0000000000000000.bss 1470000000000000000ld.comment0000000000000000.comment 1480000000000000000ldf*ABS*0000000000000000crtstuff.c 1490000000000001090lF.text0000000000000000deregister_tm_clones 15000000000000010c0lF.text0000000000000000register_tm_clones 1510000000000001100lF.text0000000000000000__do_global_dtors_aux 1520000000000004010lO.bss0000000000000001completed.8061 1530000000000003dc0lO.fini_array0000000000000000__do_global_dtors_aux_fini_array_entry 1540000000000001140lF.text0000000000000000frame_dummy 1550000000000003db8lO.init_array0000000000000000__frame_dummy_init_array_entry 1560000000000000000ldf*ABS*0000000000000000main.c 1570000000000004014lO.bss0000000000000004g_count 1580000000000004018lO.bss0000000000000004l_count.2316 1590000000000001191lF.text0000000000000028util_func 1600000000000000000ldf*ABS*0000000000000000test.c 1610000000000000000ldf*ABS*0000000000000000crtstuff.c 16200000000000021eclO.eh_frame0000000000000000__FRAME_END__ 1630000000000000000ldf*ABS*0000000000000000 1640000000000003dc0l.init_array0000000000000000__init_array_end 1650000000000003dc8lO.dynamic0000000000000000_DYNAMIC 1660000000000003db8l.init_array0000000000000000__init_array_start 167000000000000202cl.eh_frame_hdr0000000000000000__GNU_EH_FRAME_HDR 1680000000000003fb8lO.got0000000000000000_GLOBAL_OFFSET_TABLE_ 1690000000000001000lF.init0000000000000000_init 1700000000000001270gF.text0000000000000005__libc_csu_fini 1710000000000000000w*UND*0000000000000000_ITM_deregisterTMCloneTable 1720000000000004000w.data0000000000000000data_start 1730000000000004010g.data0000000000000000_edata 1740000000000001278gF.fini0000000000000000.hidden_fini 1750000000000000000F*UND*0000000000000000printf@@GLIBC_2.2.5 17600000000000011f5gF.text000000000000000btest_func 1770000000000000000F*UND*0000000000000000__libc_start_main@@GLIBC_2.2.5 1780000000000004000g.data0000000000000000__data_start 1790000000000000000w*UND*0000000000000000__gmon_start__ 1800000000000004008gO.data0000000000000000.hidden__dso_handle 1810000000000002000gO.rodata0000000000000004_IO_stdin_used 1820000000000001149gF.text0000000000000048func 1830000000000001200gF.text0000000000000065__libc_csu_init 1840000000000004020g.bss0000000000000000_end 1850000000000001060gF.text000000000000002f_start 1860000000000004010g.bss0000000000000000__bss_start 18700000000000011b9gF.text000000000000003cmain 1880000000000004010gO.data0000000000000000.hidden__TMC_END__ 1890000000000000000w*UND*0000000000000000_ITM_registerTMCloneTable 1900000000000000000wF*UND*0000000000000000__cxa_finalize@@GLIBC_2.2.5 191Contentsofsection.interp: 19203182f6c696236342f6c642d6c696e75782d/lib64/ld-linux- 19303287838362d36342e736f2e3200x86-64.so.2. 194省略了一些無關(guān)緊要的內(nèi)容 195Contentsofsection.data: 196400000000000000000000840000000000000.........@...... 197Contentsofsection.comment: 19800004743433a20285562756e747520392e34GCC:(Ubuntu9.4 19900102e302d317562756e7475317e32302e30.0-1ubuntu1~20.0 2000020342e312920392e342e30004.1)9.4.0. 201Disassemblyofsection.init: 2020000000000001000<_init>: 203_init(): 2041000:f30f1efaendbr64 2051004:4883ec08sub$0x8,%rsp 2061008:488b05d92f0000mov0x2fd9(%rip),%rax#3fe8<__gmon_start__> 207100f:4885c0test%rax,%rax 2081012:7402je1016<_init+0x16> 2091014:ffd0callq*%rax 2101016:4883c408add$0x8,%rsp 211101a:c3retq 212Disassemblyofsection.plt: 2130000000000001020<.plt>: 2141020:ff359a2f0000pushq0x2f9a(%rip)#3fc0<_GLOBAL_OFFSET_TABLE_+0x8> 2151026:f2ff259b2f0000bndjmpq*0x2f9b(%rip)#3fc8<_GLOBAL_OFFSET_TABLE_+0x10> 216102d:0f1f00nopl(%rax) 2171030:f30f1efaendbr64 2181034:6800000000pushq$0x0 2191039:f2e9e1ffffffbndjmpq1020<.plt> 220103f:90nop 221Disassemblyofsection.plt.got: 2220000000000001040<__cxa_finalize@plt>: 2231040:f30f1efaendbr64 2241044:f2ff25ad2f0000bndjmpq*0x2fad(%rip)#3ff8<__cxa_finalize@GLIBC_2.2.5> 225104b:0f1f440000nopl0x0(%rax,%rax,1) 226Disassemblyofsection.plt.sec: 2270000000000001050: 2281050:f30f1efaendbr64 2291054:f2ff25752f0000bndjmpq*0x2f75(%rip)#3fd0@glibc_2.2.5> 230105b:0f1f440000nopl0x0(%rax,%rax,1) 231Disassemblyofsection.text: 2320000000000001060<_start>: 233_start(): 2341060:f30f1efaendbr64 2351064:31edxor%ebp,%ebp 2361066:4989d1mov%rdx,%r9 2371069:5epop%rsi 238106a:4889e2mov%rsp,%rdx 239106d:4883e4f0and$0xfffffffffffffff0,%rsp 2401071:50push%rax 2411072:54push%rsp 2421073:4c8d05f6010000lea0x1f6(%rip),%r8#1270<__libc_csu_fini> 243107a:488d0d7f010000lea0x17f(%rip),%rcx#1200<__libc_csu_init> 2441081:488d3d31010000lea0x131(%rip),%rdi#11b92451088:ff15522f0000callq*0x2f52(%rip)#3fe0<__libc_start_main@GLIBC_2.2.5> 246108e:f4hlt 247108f:90nop 2480000000000001090: 249deregister_tm_clones(): 2501090:488d3d792f0000lea0x2f79(%rip),%rdi#4010<__TMC_END__> 2511097:488d05722f0000lea0x2f72(%rip),%rax#4010<__TMC_END__> 252109e:4839f8cmp%rdi,%rax 25310a1:7415je10b80x28> 25410a3:488b052e2f0000mov0x2f2e(%rip),%rax#3fd8<_ITM_deregisterTMCloneTable> 25510aa:4885c0test%rax,%rax 25610ad:7409je10b80x28> 25710af:ffe0jmpq*%rax 25810b1:0f1f8000000000nopl0x0(%rax) 25910b8:c3retq 26010b9:0f1f8000000000nopl0x0(%rax) 26100000000000010c0: 262register_tm_clones(): 26310c0:488d3d492f0000lea0x2f49(%rip),%rdi#4010<__TMC_END__> 26410c7:488d35422f0000lea0x2f42(%rip),%rsi#4010<__TMC_END__> 26510ce:4829fesub%rdi,%rsi 26610d1:4889f0mov%rsi,%rax 26710d4:48c1ee3fshr$0x3f,%rsi 26810d8:48c1f803sar$0x3,%rax 26910dc:4801c6add%rax,%rsi 27010df:48d1fesar%rsi 27110e2:7414je10f80x38> 27210e4:488b05052f0000mov0x2f05(%rip),%rax#3ff0<_ITM_registerTMCloneTable> 27310eb:4885c0test%rax,%rax 27410ee:7408je10f80x38> 27510f0:ffe0jmpq*%rax 27610f2:660f1f440000nopw0x0(%rax,%rax,1) 27710f8:c3retq 27810f9:0f1f8000000000nopl0x0(%rax) 2790000000000001100<__do_global_dtors_aux>: 280__do_global_dtors_aux(): 2811100:f30f1efaendbr64 2821104:803d052f000000cmpb$0x0,0x2f05(%rip)#4010<__TMC_END__> 283110b:752bjne1138<__do_global_dtors_aux+0x38> 284110d:55push%rbp 285110e:48833de22e0000cmpq$0x0,0x2ee2(%rip)#3ff8<__cxa_finalize@GLIBC_2.2.5> 2861115:00 2871116:4889e5mov%rsp,%rbp 2881119:740cje1127<__do_global_dtors_aux+0x27> 289111b:488b3de62e0000mov0x2ee6(%rip),%rdi#4008<__dso_handle> 2901122:e819ffffffcallq1040<__cxa_finalize@plt> 2911127:e864ffffffcallq1090292112c:c605dd2e000001movb$0x1,0x2edd(%rip)#4010<__TMC_END__> 2931133:5dpop%rbp 2941134:c3retq 2951135:0f1f00nopl(%rax) 2961138:c3retq 2971139:0f1f8000000000nopl0x0(%rax) 2980000000000001140: 299frame_dummy(): 3001140:f30f1efaendbr64 3011144:e977ffffffjmpq10c03020000000000001149: 303func(): 3041149:f30f1efaendbr64 305114d:55push%rbp 306114e:4889e5mov%rsp,%rbp 3071151:8b05c12e0000mov0x2ec1(%rip),%eax#4018 3081157:83c001add$0x1,%eax 309115a:8905b82e0000mov%eax,0x2eb8(%rip)#4018 3101160:8b05ae2e0000mov0x2eae(%rip),%eax#4014 3111166:83c001add$0x1,%eax 3121169:8905a52e0000mov%eax,0x2ea5(%rip)#4014 313116f:8b159f2e0000mov0x2e9f(%rip),%edx#4014 3141175:8b059d2e0000mov0x2e9d(%rip),%eax#4018 315117b:89c6mov%eax,%esi 316117d:488d3d800e0000lea0xe80(%rip),%rdi#2004<_IO_stdin_used+0x4> 3171184:b800000000mov$0x0,%eax 3181189:e8c2feffffcallq1050319118e:90nop 320118f:5dpop%rbp 3211190:c3retq 3220000000000001191: 323util_func(): 3241191:f30f1efaendbr64 3251195:55push%rbp 3261196:4889e5mov%rsp,%rbp 3271199:4883ec10sub$0x10,%rsp 328119d:897dfcmov%edi,-0x4(%rbp) 32911a0:8b45fcmov-0x4(%rbp),%eax 33011a3:89c6mov%eax,%esi 33111a5:488d3d720e0000lea0xe72(%rip),%rdi#201e<_IO_stdin_used+0x1e> 33211ac:b800000000mov$0x0,%eax 33311b1:e89afeffffcallq105033411b6:90nop 33511b7:c9leaveq 33611b8:c3retq 33700000000000011b9<main>: 338main(): 33911b9:f30f1efaendbr64 34011bd:55push%rbp 34111be:4889e5mov%rsp,%rbp 34211c1:b800000000mov$0x0,%eax 34311c6:e87effffffcallq114934411cb:b800000000mov$0x0,%eax 34511d0:e874ffffffcallq114934611d5:b800000000mov$0x0,%eax 34711da:e86affffffcallq114934811df:bf0a000000mov$0xa,%edi 34911e4:e8a8ffffffcallq119135011e9:e807000000callq11f535111ee:b800000000mov$0x0,%eax 35211f3:5dpop%rbp 35311f4:c3retq 35400000000000011f5: 355test_func(): 35611f5:f30f1efaendbr64 35711f9:55push%rbp 35811fa:4889e5mov%rsp,%rbp 35911fd:90nop 36011fe:5dpop%rbp 36111ff:c3retq 3620000000000001200<__libc_csu_init>: 363__libc_csu_init(): 3641200:f30f1efaendbr64 3651204:4157push%r15 3661206:4c8d3dab2b0000lea0x2bab(%rip),%r15#3db8<__frame_dummy_init_array_entry> 367120d:4156push%r14 368120f:4989d6mov%rdx,%r14 3691212:4155push%r13 3701214:4989f5mov%rsi,%r13 3711217:4154push%r12 3721219:4189fcmov%edi,%r12d 373121c:55push%rbp 374121d:488d2d9c2b0000lea0x2b9c(%rip),%rbp#3dc0<__do_global_dtors_aux_fini_array_entry> 3751224:53push%rbx 3761225:4c29fdsub%r15,%rbp 3771228:4883ec08sub$0x8,%rsp 378122c:e8cffdffffcallq1000<_init> 3791231:48c1fd03sar$0x3,%rbp 3801235:741fje1256<__libc_csu_init+0x56> 3811237:31dbxor%ebx,%ebx 3821239:0f1f8000000000nopl0x0(%rax) 3831240:4c89f2mov%r14,%rdx 3841243:4c89eemov%r13,%rsi 3851246:4489e7mov%r12d,%edi 3861249:41ff14dfcallq*(%r15,%rbx,8) 387124d:4883c301add$0x1,%rbx 3881251:4839ddcmp%rbx,%rbp 3891254:75eajne1240<__libc_csu_init+0x40> 3901256:4883c408add$0x8,%rsp 391125a:5bpop%rbx 392125b:5dpop%rbp 393125c:415cpop%r12 394125e:415dpop%r13 3951260:415epop%r14 3961262:415fpop%r15 3971264:c3retq 3981265:66662e0f1f8400data16nopw%cs:0x0(%rax,%rax,1) 399126c:00000000 4000000000000001270<__libc_csu_fini>: 401__libc_csu_fini(): 4021270:f30f1efaendbr64 4031274:c3retq 404Disassemblyofsection.fini: 4050000000000001278<_fini>: 406_fini(): 4071278:f30f1efaendbr64 408127c:4883ec08sub$0x8,%rsp 4091280:4883c408add$0x8,%rsp 4101284:c3retq @plt>@plt>++++@plt>老規(guī)矩,看不懂全部不重要,找你能看得懂的。還是找到 l_count 、g_count、util_test 這幾個(gè)來吧。04a8ea3e-312c-11ee-9e74-dac502259ad0.png看樣子也沒啥特殊的,所以問題的關(guān)鍵還在前一步:鏈接器那里。綜上可知,static的修飾主要是給編譯器做了提示,從而生成的obj文件中帶了 local屬性,這樣就告訴鏈接器,不能擴(kuò)大這些被local修飾過的內(nèi)容的使用范圍,從而達(dá)到了教科書上面說的那樣static的作用效果。其實(shí)還有一個(gè)方法,就是你寫一個(gè)帶static和不帶static的,比如都是全局變量的兩個(gè),通過反匯編來對比分析,這樣也可以快速看出核心區(qū)別,就留給讀者去探索吧。再留一個(gè)疑問:編譯器、鏈接器 如何做到一個(gè)static修飾的局部變量,只能被定義的當(dāng)前函數(shù)內(nèi)訪問的?這個(gè)問題,有點(diǎn)深入,也留給讀者去探索吧。
		5 一種繞開static限制的方法
談到繞開static的限制,其實(shí)本文第1小節(jié)的那個(gè)問題例子就是一個(gè)很好的思路和方法。要想繞開static的限制,無非就是:將被static修飾的函數(shù)轉(zhuǎn)換為沒有被static修飾的函數(shù)!或者將被static修飾的變量轉(zhuǎn)換為沒有被static修飾的變量!這個(gè)做法,還有一個(gè)行業(yè)名詞叫:封裝。在第1小節(jié)中,代碼中演示的是將被static修飾的變量,通過傳出其地址,以指針的形式導(dǎo)出給外部模塊使用。下面的代碼片段,將展示將被static修飾的函數(shù),轉(zhuǎn)換為沒有被static修飾的函數(shù),從而給外部模塊使用。

		1test_a.c  2staticinttest_func_in_a(inta)  3{  4returna+1;  5}  6inttest_func_in_a_ex(inta)  7{  8returntest_func_in_a(a);  9} 10---------------------------- 11test_b.c 12inttest_func_in_b(void) 13{ 14inta=1; 15intb; 16//calltest_func_in_afunctionfailbecauseof"static" 17//b=test_func_in_a(a) 18//calltest_func_in_a_exfunctionokwithout"static" 19b=test_func_in_a_ex(a) 20returnb; 21}示例代碼很簡單,僅僅就是在_test_a.c 中,編寫一個(gè)不被static修飾的函數(shù) test_func_in_a_ex,然后它去調(diào)用被static修飾的test_func_in_a函數(shù),這樣就輕松繞開了static的限制。你學(xué)會(huì)了嗎?
		6 拓展延伸:如何調(diào)用靜態(tài)庫里的被static修飾的函數(shù)?
關(guān)于這個(gè)擴(kuò)展延伸,其實(shí)我很早就起草了一篇博文想寫這個(gè)內(nèi)容來著,但是一直拖,一直拖,直到現(xiàn)在還沒生產(chǎn)。索性就在本文做個(gè)牽引吧!個(gè)人認(rèn)為,對于此問題,應(yīng)該分為兩個(gè)場景:靜態(tài)庫的代碼,你有修改的權(quán)限;或者你能找到人來修改;比如,公司內(nèi)部不同團(tuán)隊(duì)直接的公有庫代碼;靜態(tài)庫的代碼,你完全沒辦法查看源碼或修改源碼;比如一些第三方的庫。針對這兩種不同的場景,可能采取的方式是不一樣的,你覺得應(yīng)該如何做最好呢?如果你也對此問題感興趣,請關(guān)注我的后續(xù)的拆解博文。

原文:https://club.rt-thread.org/ask/article/1b38085300b58f82.html

作者:recan

———————End——————


點(diǎn)擊閱讀原文進(jìn)入官網(wǎng)

??????


原文標(biāo)題:【知識(shí)科普】C語言的static究竟限制了誰

文章出處:【微信公眾號:RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1239

    瀏覽量

    39437

原文標(biāo)題:【知識(shí)科普】C語言的static究竟限制了誰

文章出處:【微信號:RTThread,微信公眾號:RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    C++語言基礎(chǔ)知識(shí)

    電子發(fā)燒友網(wǎng)站提供《C++語言基礎(chǔ)知識(shí).pdf》資料免費(fèi)下載
    發(fā)表于 07-19 10:58 ?6次下載

    嵌入式C語言面試大挑戰(zhàn)

    C++中static關(guān)鍵字除了具有C中的作用還有在類中的使用在類中,static可以用來修飾靜態(tài)數(shù)據(jù)成員和靜態(tài)成員方法靜態(tài)數(shù)據(jù)成員
    發(fā)表于 03-05 14:18 ?238次閱讀
    嵌入式<b class='flag-5'>C</b><b class='flag-5'>語言</b>面試大挑戰(zhàn)

    c語言,c++,java,python區(qū)別

    C語言、C++、Java和Python是四種常見的編程語言,各有優(yōu)點(diǎn)和特點(diǎn)。 C語言
    的頭像 發(fā)表于 02-05 14:11 ?1374次閱讀

    C語言必備知識(shí)頭文件包含

    頭文件在C語言中是非常重要的組成部分。
    的頭像 發(fā)表于 12-01 18:20 ?1517次閱讀

    C語言運(yùn)行環(huán)境是什么

    C語言運(yùn)行環(huán)境(C language runtime environment)是指在執(zhí)行C語言程序時(shí)所需的軟件及硬件環(huán)境。
    的頭像 發(fā)表于 11-27 16:13 ?2857次閱讀

    如何選擇創(chuàng)建c語言c++

    選擇創(chuàng)建 C 語言C++ 都需要綜合考慮多個(gè)因素。在決定使用哪種語言之前,我們需要對這兩種語言的特點(diǎn)、優(yōu)缺點(diǎn)、適用場景、學(xué)習(xí)成本等進(jìn)行全
    的頭像 發(fā)表于 11-27 15:58 ?458次閱讀

    c語言程序設(shè)計(jì)基礎(chǔ)知識(shí)點(diǎn)

    程序設(shè)計(jì)的基礎(chǔ)知識(shí)點(diǎn)。 首先,我們將從C語言的數(shù)據(jù)類型和變量開始。C語言提供多種數(shù)據(jù)類型,包括
    的頭像 發(fā)表于 11-27 15:25 ?1336次閱讀

    C語言編程必備知識(shí)合集

    電子發(fā)燒友網(wǎng)站提供《C語言編程必備知識(shí)合集.zip》資料免費(fèi)下載
    發(fā)表于 11-21 09:34 ?0次下載
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>編程必備<b class='flag-5'>知識(shí)</b>合集

    static關(guān)鍵字的三種用法

    C語言中,關(guān)鍵字"static"可以用于不同的上下文,具有不同的作用。以下是"static"在C語言
    的頭像 發(fā)表于 11-10 08:00 ?416次閱讀
    <b class='flag-5'>static</b>關(guān)鍵字的三種用法

    C語言函數(shù)返回1和返回0究竟哪個(gè)好?

    C語言函數(shù)返回1和返回0究竟哪個(gè)好? 在C語言中,很多函數(shù)需要返回一個(gè)值來表示函數(shù)是否成功執(zhí)行。而在很多情況下,通常會(huì)選擇讓函數(shù)返回1或0,
    的頭像 發(fā)表于 10-31 14:43 ?795次閱讀

    科普|電源管理知識(shí)

    科普|電源管理知識(shí)
    的頭像 發(fā)表于 10-17 16:31 ?497次閱讀
    <b class='flag-5'>科普</b>|電源管理<b class='flag-5'>知識(shí)</b>

    Java中對static關(guān)鍵詞的介紹

    static 是Java的一個(gè)關(guān)鍵字,可以用來修飾成員變量、修飾成員方法、構(gòu)造靜態(tài)代碼塊、實(shí)現(xiàn)靜態(tài)導(dǎo)包以及實(shí)現(xiàn)靜態(tài)內(nèi)部類,下面我們來分別介紹。 1、修飾成員變量 用 static 修飾成員變量
    的頭像 發(fā)表于 10-11 15:26 ?385次閱讀
    Java中對<b class='flag-5'>static</b>關(guān)鍵詞的介紹

    static定義內(nèi)部類

    是一個(gè)獨(dú)立的程序類。需要注意,static定義的不管是類還是方法只能夠訪問static成員, 所以static定義的內(nèi)部類只能夠訪問外部內(nèi)中的st
    的頭像 發(fā)表于 10-10 16:08 ?460次閱讀

    C語言指針講解

      C語言可以說是工科學(xué)生必不可少的編程語言,尤其是嵌入式的應(yīng)用中C語言更是大廈之基,甚至在我
    發(fā)表于 10-01 13:25 ?261次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>指針講解

    C語言的基礎(chǔ)知識(shí)

    C語言是一種高級編程語言,廣泛應(yīng)用于操作系統(tǒng)、嵌入式系統(tǒng)、游戲開發(fā)等領(lǐng)域。它由貝爾實(shí)驗(yàn)室的Dennis Ritchie在1972年開發(fā)而成,是Unix系統(tǒng)中最常用的編程語言之一。
    發(fā)表于 09-28 17:27 ?1363次閱讀