天天看點

c語言中關鍵字static作用,c語言中static關鍵字的作用

c語言中關鍵字static作用,c語言中static關鍵字的作用

8種機械鍵盤軸體對比

本人程式員,要買一個寫代碼的鍵盤,請問紅軸和茶軸怎麼選?

static修飾局部變量

首先來看一段程式,思考一下該程式調用foo、bar函數後輸出a的值分别會是多少呢?

123456789101112131415161718192021#include

int main(){

foo();

bar();

foo();

bar();

return 0;

}

void foo() {

static int a = 0x12345678;

++a;

printf("a in foo(), location: 0x%x, current value: 0x%xn", &a, a);

}

void bar() {

static int a = 0x87654321;

++a;

printf("a in bar(), location: 0x%x, current value: 0x%xn", &a, a);

}

使用gcc編譯上面的程式,運作程式,控制台輸出如下圖

c語言中關鍵字static作用,c語言中static關鍵字的作用

從程式的輸出我們可以看到foo和bar中的a的存儲位址不同,而且每次調用foo和bar,它們自己的變量a的值都增加了1。再來看一下它們的反彙編代碼

c語言中關鍵字static作用,c語言中static關鍵字的作用

可以看到a并不在棧上。使用objdump -h Test.exe獲得各個段的資訊。可以看到.data段将被加載到0000000000403000處,它和列印出來的變量a的存儲位址很接近。猜測變量a可能就在.data段。Test.exe: file format pei-x86-64

Sections:

Idx Name Size VMA LMA File off Algn

0 .text 00001db8 0000000000401000 0000000000401000 00000600 2**4

CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA

1 .data 000000a8 0000000000403000 0000000000403000 00002400 2**4

CONTENTS, ALLOC, LOAD, DATA

2 .rdata 00000830 0000000000404000 0000000000404000 00002600 2**4

CONTENTS, ALLOC, LOAD, READONLY, DATA

3 .pdata 00000288 0000000000405000 0000000000405000 00003000 2**2

CONTENTS, ALLOC, LOAD, READONLY, DATA

4 .xdata 0000023c 0000000000406000 0000000000406000 00003400 2**2

CONTENTS, ALLOC, LOAD, READONLY, DATA

5 .bss 00000a50 0000000000407000 0000000000407000 00000000 2**6

ALLOC

6 .idata 00000818 0000000000408000 0000000000408000 00003800 2**2

CONTENTS, ALLOC, LOAD, DATA

7 .CRT 00000068 0000000000409000 0000000000409000 00004200 2**3

CONTENTS, ALLOC, LOAD, DATA

8 .tls 00000068 000000000040a000 000000000040a000 00004400 2**5

CONTENTS, ALLOC, LOAD, DATA

9 .debug_aranges 00000450 000000000040b000 000000000040b000 00004600 2**4

CONTENTS, READONLY, DEBUGGING

10 .debug_info 0000c127 000000000040c000 000000000040c000 00004c00 2**0

CONTENTS, READONLY, DEBUGGING

11 .debug_abbrev 00001b04 0000000000419000 0000000000419000 00010e00 2**0

CONTENTS, READONLY, DEBUGGING

12 .debug_line 00001864 000000000041b000 000000000041b000 00012a00 2**0

CONTENTS, READONLY, DEBUGGING

13 .debug_frame 00000ba8 000000000041d000 000000000041d000 00014400 2**3

CONTENTS, READONLY, DEBUGGING

14 .debug_str 00000300 000000000041e000 000000000041e000 00015000 2**0

CONTENTS, READONLY, DEBUGGING

15 .debug_loc 00002c70 000000000041f000 000000000041f000 00015400 2**0

CONTENTS, READONLY, DEBUGGING

16 .debug_ranges 00000520 0000000000422000 0000000000422000 00018200 2**0

CONTENTS, READONLY, DEBUGGING

接下來确認變量a是不是在.data段。

使用指令objdump -s -j .data Test.exe檢視.data段的内容,可以看到如下的輸出

c語言中關鍵字static作用,c語言中static關鍵字的作用

果然在403010這一行看到了foo和bar兩個函數裡的a的兩個初始值,說明本例中的static局部變量存儲在.data段。

至此我們可以看出,當static修飾局部變量時,這個變量将會存儲于靜态資料區。且這個變量的作用域沒有發生變化,仍然限于函數(子產品)内部。

static修飾函數

測試代碼mod1.c和mod2.c如下

mod1.c

123static int foo() {

return 1;

}

mod2.c

12345678#include

extern int foo();

int main() {

printf(foo());

return 0;

}

輸入gcc mod1.c mod2.c 指令,控制台輸出如下:mod2.c:(.text+0xe): undefined reference to `foo’

collect2.exe: error: ld returned 1 exit status

這表明gcc在連結的時候找不到符号foo,因為mod1.c中的foo函數在mod2.c中不可見。

接下來修改mod2.c

12345678910#include

static int foo() {

return 2;

}

int main() {

printf(foo());

return 0;

}

再次編譯連結,沒有出現錯誤。運作程式,控制台輸出了2;也就是說mod2.c中調用的foo()位于mod2.c而非mod1.c。

以上現象表明,在C語言中,函數預設是全局的,static修飾函數時會使該函數的作用域被限制在了定義該變量的源檔案内。

static修飾全局變量

其效果和修飾函數時相同,不再贅述。

總結static修飾局部變量會使該變量存儲于靜态資料區。

沒有使用static修飾的全局變量或函數在所有子產品都可見,而使用static修飾的全局變量或函數隻在目前子產品可見(隻在定義該變量或函數的源檔案内有效)。static改變了全局變量或函數預設的作用域。