C语言函数内static关键字 疑惑
static關(guān)鍵字有兩類使用:函數(shù)外使用和和函數(shù)內(nèi)使用,其中函數(shù)外使用主要用來(lái)限制被修飾的函數(shù)或變量作用域?yàn)楸疚募?沒(méi)什么可多說(shuō)的,下面重點(diǎn)說(shuō)一下static關(guān)鍵字在函數(shù)體內(nèi)的用法.
如下面的代碼:
#include<stdio.h> void test(){static int a=1;printf("%d",a++); } void main(){int i;for (i=0;i<5;i++)test(); }輸出為12345,如果去掉static關(guān)鍵字,輸出將是11111.
我們來(lái)看一下使用了static關(guān)鍵字后的匯編代碼(只保留了關(guān)鍵部分):
可以看到下面三行匯編代碼實(shí)際完成的是a++操作,如果有不理解第二條指令的可以參考我的上一篇博客.
movl a.1933, %eaxleal 1(%eax), %edxmovl %edx, a.1933等等,我的變量名不是a嗎?a.1933是什么玩意兒?其實(shí)這個(gè)a.1933像極了一個(gè)全局變量.不信看下面的代碼:
#include<stdio.h> int a=1; void test(){printf("%d",a++); } void main(){int i;for (i=0;i<5;i++)test(); }其關(guān)鍵的匯編代碼為:
a:.long 1 .LC0:.string "%d" test: .LFB0:pushl %ebpmovl %esp, %ebpsubl $8, %espmovl a, %eaxleal 1(%eax), %edxmovl %edx, asubl $8, %esppushl %eaxpushl $.LC0call printfaddl $16, %espnopleaveret看看,何止像,從匯編的角度來(lái)看,這里的a和上面的a.1933根本就是一回事嘛.所以函數(shù)內(nèi)的static變量和全局變量從匯編的角度看本質(zhì)上是一樣的.這也就解釋了為什么test()退出后static修飾的a還存在的問(wèn)題,因?yàn)槿思腋肿兞康牡匚灰粯勇?那如何解釋1933這個(gè)后綴呢?其實(shí)這個(gè)是C編譯器的限制,也就是說(shuō)你只有在匯編后才知道函數(shù)內(nèi)static修飾的變量真正叫什么名字,而這個(gè)名字只在該函數(shù)體內(nèi)才知道,外部函數(shù)是不知道這個(gè)真名的.換句話說(shuō),C編譯器就是靠這個(gè)別名的辦法限制了外部函數(shù)對(duì)其的訪問(wèn).
但是由于這兩者實(shí)在太像了,我們可以欺騙一下編譯器,看下面的代碼:
這個(gè)代碼連接時(shí)一定不能通過(guò),原因是test2中的a根本沒(méi)有定義.由于static int a只存在于test內(nèi),test2無(wú)法訪問(wèn)到.但是上面的代碼卻可以匯編通過(guò)(關(guān)鍵代碼如下):
test: .LFB0:movl a.1933, %eaxleal 1(%eax), %edxmovl %edx, a.1933subl $8, %esppushl %eaxpushl $.LC0call printftest2: .LFB1:movl a, %eaxsubl $8, %esppushl %eaxpushl $.LC0call printfa.1933:.long 1可以看到static int a被編譯器在test中別名為了a.1933,而test2并不知道這一點(diǎn).因此我們可以手動(dòng)修改test2讓它知道這一點(diǎn).即把a(bǔ)別名成a.1933,這樣再編譯執(zhí)行,這樣可以順利輸出12.而此時(shí)的static int a完全被改造成了全局變量.
總結(jié)
以上是生活随笔為你收集整理的C语言函数内static关键字 疑惑的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于有源晶振倍频干扰的问题
- 下一篇: arm交叉编译bluez-5.25