C語言如何初始化靜態(tài)變量

通過一個例子說明C語言如何初始化靜態(tài)變量。

給出C語言代碼例子

這個例子在linux gcc x86_64環(huán)境下驗證删掀。

typedef int (* Fun)(void * obj, int argc, int *argv);

struct FunctionSpec {
    const char      *name;  /* 8 byte */
    Fun             call;   /* 8 byte */
    unsigned char   nargs;  /* 1 byte */
    unsigned char   flags;  /* 1 byte*/ 
    unsigned short  extra;  /* 2 byte */
};

static int foo1(void *obj, int argc, int *argv) {  return 0; }

static int foo2(void *obj, int argc, int *argv) { return 0; }

static int foo3(void *obj, int argc, int *argv) { return 0; }

static struct FunctionSpec my_functions[] = {
    {"foo1",         foo1,    11, 22, 33},
    {"foo2",         foo2,    44, 55},
    {"foo3",         foo3,    66},
    {0}
};

int main(int argc, char * argv[])
{
    printf("sizeof FunctionSpec=%d\n", sizeof(struct FunctionSpec));
    printf("sizeof my_functions=%d\n", sizeof(my_functions));
    return 0;
}

說明:

  1. 這個例子定義了一個靜態(tài)數(shù)組變量my_functions翔冀;
  2. 數(shù)組變量的成員類型是結(jié)構(gòu)體FunctionSpec,包含5個域
  3. 數(shù)組變量的大小是4披泪,即有4個成員
    第一個成員初始化提供了5個域
    第二個成員初始化提供了4個域
    第三個成員初始化提供了3個域
    第四個成員初始化提供了1個域纤子。

也就是說,程序員為FunctionSpec類型變量的初始化款票,有些提供了全5個值控硼,而有些只提供了4個值,或者3個值徽职,甚至1個域值象颖;那么剩下沒有提供值得域會怎么處理呢。

運行步驟

  1. 編譯運行
$ gcc test.c
$ ./a.out
sizeof FunctionSpec=24
sizeof my_functions=96

說明:FunctionSpec共有5個域:

  1. 第一個域是pointer姆钉,占用8字節(jié)
  2. 第二個域也是pointer说订,占用8字節(jié)
  3. 第三個域是char,占用1字節(jié)
  4. 第四個域是char潮瓶,占用1字節(jié)
  5. 第五個域是short陶冷,占用2字節(jié)

一共需要8+8+1+1+2=20字節(jié),但是由于對齊(align)的原因毯辅,會有額外四個字節(jié)的padd對齊空間埂伦,從而實際占用空間為24字節(jié)。

查看my_functions變量的匯編代碼

因為my_functions是靜態(tài)變量思恐,從程序匯編代碼就能夠看出其變量的內(nèi)容沾谜。

    .section    .rodata
.LC0:
    .string "foo1"
.LC1:
    .string "foo2"
    .data
    .align 32
    .type   my_functions, @object
    .size   my_functions, 96
my_functions:
    .quad   .LC0      # 第一個元素: 8 字節(jié)指針指向字符串foo1的地址
    .quad   foo1      #   8 字節(jié)指針指向函數(shù)foo1的地址
    .byte   11        #   1 字節(jié)參數(shù)nargs的值
    .byte   22        #   1 字節(jié)參數(shù)flags的值
    .value  33        #   1 字節(jié)參數(shù)extra的值
    .zero   4         #   4 字節(jié)的padd, 和前面4字節(jié)構(gòu)成一個8字節(jié)的標(biāo)準(zhǔn)長度
    .quad   .LC1      # 第二個元素: 8 字節(jié)指針指向字符串foo2的地址
    .quad   foo2      #   8 字節(jié)指針指向函數(shù)foo2的地址
    .byte   44        #   1 字節(jié)參數(shù)nargs的值
    .byte   55        #   1 字節(jié)參數(shù)flags的值
    .zero   6         #   6 字節(jié)的padd, 和前面2字節(jié)構(gòu)成一個8字節(jié)的標(biāo)準(zhǔn)長度, 因為這個元素只給參數(shù)nargs和flags賦了值,剩下參數(shù)是0
    .quad   .LC2      # 第二個元素: 8 字節(jié)指針指向字符串foo3的地址
    .quad   foo3      #   8 字節(jié)指針指向函數(shù)foo3的地址
    .byte   66        #   1 字節(jié)參數(shù)nargs的值
    .zero   7         #   7 字節(jié)的padd, 和前面2字節(jié)構(gòu)成一個8字節(jié)的標(biāo)準(zhǔn)長度, 因為這個元素只給參數(shù)nargs賦了值胀莹,剩下參數(shù)都是0
    .quad   0         # 第三個元素
    .zero   16        #   所有的參數(shù)都是缺省值0
    .section    .rodata

我們看到?jīng)]有分配的域編譯器都生成.zero匯編偽代碼基跑。
下面我們再看一下最終生成的可執(zhí)行文件a.out里面相關(guān)的內(nèi)容

$ objdump -D -S a.out

注意因為這個反匯編出來的內(nèi)容,沒法區(qū)分是指令還是數(shù)據(jù)描焰,所有統(tǒng)統(tǒng)轉(zhuǎn)換成了指令媳否,我們只關(guān)注內(nèi)容數(shù)據(jù)即可,不必注意對應(yīng)的指令是什么荆秦,本身他們就不是指令篱竭,是強翻譯的而已。

變量my_functions的全部內(nèi)容如下:

00000000006009c0 <my_functions>:
  6009c0:   48 06                   rex.W (bad)
  6009c2:   40 00 00                add    %al,(%rax)
  6009c5:   00 00                   add    %al,(%rax)
  6009c7:   00 c4                   add    %al,%ah
  6009c9:   04 40                   add    $0x40,%al
  6009cb:   00 00                   add    %al,(%rax)
  6009cd:   00 00                   add    %al,(%rax)
  6009cf:   00 0b                   add    %cl,(%rbx)
  6009d1:   16                      (bad)
  6009d2:   21 00                   and    %eax,(%rax)
  6009d4:   00 00                   add    %al,(%rax)
  6009d6:   00 00                   add    %al,(%rax)
  6009d8:   4d 06                   rex.WRB (bad)
  6009da:   40 00 00                add    %al,(%rax)
  6009dd:   00 00                   add    %al,(%rax)
  6009df:   00 da                   add    %bl,%dl
  6009e1:   04 40                   add    $0x40,%al
  6009e3:   00 00                   add    %al,(%rax)
  6009e5:   00 00                   add    %al,(%rax)
  6009e7:   00 2c 37                add    %ch,(%rdi,%rsi,1)
  6009ea:   00 00                   add    %al,(%rax)
  6009ec:   00 00                   add    %al,(%rax)
  6009ee:   00 00                   add    %al,(%rax)
  6009f0:   52                      push   %rdx
  6009f1:   06                      (bad)
  6009f2:   40 00 00                add    %al,(%rax)
  6009f5:   00 00                   add    %al,(%rax)
  6009f7:   00 f0                   add    %dh,%al
  6009f9:   04 40                   add    $0x40,%al
  6009fb:   00 00                   add    %al,(%rax)
  6009fd:   00 00                   add    %al,(%rax)
  6009ff:   00 42 00                add    %al,0x0(%rdx)
    ...

我們知道m(xù)y_functions變量包含5條值:
第一條數(shù)據(jù)24個字節(jié)長度:

  6009c0:   48 06                   rex.W (bad)
  6009c2:   40 00 00                add    %al,(%rax)
  6009c5:   00 00                   add    %al,(%rax)
  6009c7:   00 c4                   add    %al,%ah
  6009c9:   04 40                   add    $0x40,%al
  6009cb:   00 00                   add    %al,(%rax)
  6009cd:   00 00                   add    %al,(%rax)
  6009cf:   00 0b                   add    %cl,(%rbx)
  6009d1:   16                      (bad)
  6009d2:   21 00                   and    %eax,(%rax)
  6009d4:   00 00                   add    %al,(%rax)
  6009d6:   00 00                   add    %al,(%rax)
  1. 第一個域8字節(jié)步绸,其值為0000000000400648掺逼,指向字符串"foo1"的地址:
 400648:   66 6f                   outsw  %ds:(%rsi),(%dx)
 40064a:   6f                      outsl  %ds:(%rsi),(%dx)
 40064b:   31 00                   xor    %eax,(%rax)

其值正好是"foo1": 0x66-0x6f-0x6f-0x31-0x00

  1. 第二個域8字節(jié),其值為00000000004004c4瓤介,指向函數(shù)foo1的地址:
00000000004004c4 <foo1>:

static int foo1(void *obj, int argc, int *argv) {  return 0; }
  4004c4:   55                      push   %rbp
  4004c5:   48 89 e5                mov    %rsp,%rbp
  4004c8:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
  4004cc:   89 75 f4                mov    %esi,-0xc(%rbp)
  4004cf:   48 89 55 e8             mov    %rdx,-0x18(%rbp)
  4004d3:   b8 00 00 00 00          mov    $0x0,%eax
  4004d8:   c9                      leaveq
  4004d9:   c3                      retq
  1. 第三個域1字節(jié):0x0b = 11
  2. 第四個域1字節(jié):0x16 = 22
  3. 第五個域2自己:0x0021 = 33
  4. 最后是4字節(jié)的pad: 0x000000

后面的記錄數(shù)據(jù)一樣坪圾,不一一列舉了晓折,只是沒有顯示的值都為零。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兽泄,一起剝皮案震驚了整個濱河市漓概,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌病梢,老刑警劉巖胃珍,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蜓陌,居然都是意外死亡觅彰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進店門钮热,熙熙樓的掌柜王于貴愁眉苦臉地迎上來填抬,“玉大人,你說我怎么就攤上這事隧期§穑” “怎么了?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵仆潮,是天一觀的道長宏蛉。 經(jīng)常有香客問我,道長性置,這世上最難降的妖魔是什么拾并? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮鹏浅,結(jié)果婚禮上嗅义,老公的妹妹穿的比我還像新娘。我一直安慰自己隐砸,他們只是感情好芥喇,可當(dāng)我...
    茶點故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凰萨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪械馆。 梳的紋絲不亂的頭發(fā)上胖眷,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天,我揣著相機與錄音霹崎,去河邊找鬼珊搀。 笑死,一個胖子當(dāng)著我的面吹牛尾菇,可吹牛的內(nèi)容都是我干的境析。 我是一名探鬼主播囚枪,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼劳淆!你這毒婦竟也來了链沼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤沛鸵,失蹤者是張志新(化名)和其女友劉穎括勺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體曲掰,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡疾捍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了栏妖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乱豆。...
    茶點故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吊趾,靈堂內(nèi)的尸體忽然破棺而出宛裕,到底是詐尸還是另有隱情,我是刑警寧澤趾徽,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布续滋,位于F島的核電站,受9級特大地震影響孵奶,放射性物質(zhì)發(fā)生泄漏疲酌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一了袁、第九天 我趴在偏房一處隱蔽的房頂上張望朗恳。 院中可真熱鬧,春花似錦载绿、人聲如沸粥诫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怀浆。三九已至,卻和暖如春怕享,著一層夾襖步出監(jiān)牢的瞬間执赡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工函筋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沙合,地道東北人。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓跌帐,卻偏偏與公主長得像首懈,于是被迫代替她去往敵國和親绊率。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,687評論 2 351

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理究履,服務(wù)發(fā)現(xiàn)滤否,斷路器,智...
    卡卡羅2017閱讀 134,637評論 18 139