自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C 語(yǔ)言數(shù)組在內(nèi)存中是怎樣表示的?

開發(fā)
微信群里有同學(xué)問C語(yǔ)言中數(shù)組在內(nèi)存中是怎樣表示的,今天就給大家聊聊這個(gè)話題。

微信群里有同學(xué)問C語(yǔ)言中數(shù)組在內(nèi)存中是怎樣表示的,今天就給大家聊聊這個(gè)話題。

開局一張圖:

圖片

這個(gè)是經(jīng)典的Linux進(jìn)程內(nèi)存布局,通常我們使用的數(shù)據(jù)存在這樣幾個(gè)地方:

  • 棧區(qū),Stack
  • 全局區(qū),Global
  • 堆區(qū),Heap

接下來(lái)我們分別看一下C語(yǔ)言中的數(shù)組在這幾個(gè)區(qū)域是怎樣表示的,注意,小風(fēng)哥的機(jī)器是x86 64位。

數(shù)組與棧區(qū)

來(lái)看一段極其簡(jiǎn)單的代碼:

void arr_on_stack() {
int arr[6];

arr[0]=100;
arr[1]=200;
arr[2]=300;
arr[3]=400;
arr[4]=500;
arr[5]=600;

int a = arr[0];
}

我們定義了一個(gè)局部變量arr作為int類型的數(shù)組,然后分別將100-600寫到了數(shù)組中,那么數(shù)組arr在內(nèi)存中是怎樣表示的呢?

首先我們編譯一下:

# gcc -g -fno-stack-protector a.c

注意,-fno-stack-protector選項(xiàng)是為了禁止堆棧保護(hù),讓匯編更容易懂些。

好啦,一切準(zhǔn)備就緒,可以庖丁解牛啦,使用的刀就是gdb,代碼面前了無(wú)秘密,gdb面前程序的運(yùn)行時(shí)(run time)了無(wú)秘密。

用gdb來(lái)調(diào)試剛剛編譯出來(lái)的程序,這里看一下arr_on_stack函數(shù)的匯編指令:

(gdb) disassemble arr_on_stack
Dump of assembler code for function arr_on_stack:
0x0000000000400526 <+0>: push %rbp
0x0000000000400527 <+1>: mov %rsp,%rbp
0x000000000040052a <+4>: movl $0x64,-0x20(%rbp)
0x0000000000400531 <+11>: movl $0xc8,-0x1c(%rbp)
0x0000000000400538 <+18>: movl $0x12c,-0x18(%rbp)
0x000000000040053f <+25>: movl $0x190,-0x14(%rbp)
0x0000000000400546 <+32>: movl $0x1f4,-0x10(%rbp)
0x000000000040054d <+39>: movl $0x258,-0xc(%rbp)
=> 0x0000000000400554 <+46>: mov -0x20(%rbp),%eax
0x0000000000400557 <+49>: mov %eax,-0x4(%rbp)
0x000000000040055a <+52>: nop
0x000000000040055b <+53>: pop %rbp
0x000000000040055c <+54>: retq
End of assembler dump.

我們?cè)谥暗奈恼隆逗瘮?shù)在內(nèi)存中是怎樣表示的?》多次提到過,每個(gè)函數(shù)在運(yùn)行起來(lái)后都有屬于自己的棧幀,棧幀組成棧區(qū),此時(shí)arr_on_stack這個(gè)函數(shù)的棧區(qū)在哪里呢?答案就在寄存器rbp中。

我們來(lái)看一下rbp寄存器指向了哪里?

(gdb) p $rbp
$3 = (void *) 0x7ffffffee2a0

啊哈,原來(lái)?xiàng)?x7ffffffee2a0這個(gè)地方,那么我們的數(shù)組arr在哪里呢?別著急,這條指令會(huì)告訴我們答案:

0x000000000040052a <+4>:     movl   $0x64,-0x20(%rbp)

這行指令的含義是說(shuō)把100(0x64)放到rbp寄存器減去0x20的地方,顯然這就是數(shù)組的開頭,讓我們來(lái)計(jì)算一下rbp寄存器減去0x20:

0x7ffffffee2a0(%rbp) - 0x20 =  0x7ffffffee280

因此,我們預(yù)測(cè)arr應(yīng)該在0x7ffffffee280這個(gè)位置上。

接下來(lái)我們用gdb驗(yàn)證一下:

(gdb) p &arr
$2 = (int (*)[6]) 0x7ffffffee280

哈哈,怎么樣,是不是和我們猜想的一樣,數(shù)組arr的確就放在了0x7ffffffee280這個(gè)位置,是這樣存儲(chǔ)的:

圖片

這就是C語(yǔ)言中所謂的數(shù)組了,無(wú)非就是從0x7ffffffee280 到 0x7ffffffee298這一段內(nèi)存嘛,數(shù)組在棧區(qū)就是這么表示的!

數(shù)組與全局區(qū)

同樣看一段代碼:

int global_array[6];

void arr_on_global() {
global_array[0]=1;
global_array[1]=2;
global_array[2]=3;
global_array[3]=4;
global_array[4]=5;
global_array[5]=6;

int b = global_array[0];
}

同樣使用# gcc -g -fno-stack-protector a.c編譯,然后用gdb加斷點(diǎn)在int b = global_array[0]這行代碼,看下全局變量global_array的內(nèi)存位置:

(gdb) p &global_array
$12 = (int (*)[6]) 0x601050 <global_array>

gdb告訴我們數(shù)組global_array存放在內(nèi)存0x601050這個(gè)地址上。

注意0x601050這個(gè)地址和剛才看到的0x7ffffffee280這個(gè)地址相去甚遠(yuǎn),為什么呢?

再看下開局那張圖:

圖片

全局區(qū)幾乎在最底部,棧區(qū)在最頂部,所以相差很遠(yuǎn)。

接下來(lái)讓我們看看0x601050這個(gè)內(nèi)存區(qū)域中到底保存了些啥?

我們使用命令x/6wd 0x601050,這個(gè)命令告訴gdb從0x601050這個(gè)位置開始以32bit為單位用10進(jìn)制依次打印6次,讓我們來(lái)看看打印的是什么?

(gdb) x/6wd 0x601050
0x601050 <global_array>: 1 2 3 4
0x601060 <global_array+16>: 5 6

哈哈,怎么樣,是不是正是全局變量global_array中存放的內(nèi)容:圖片

這就是C語(yǔ)言中所謂的數(shù)組了,無(wú)非就是從 0x601050到 0x601068這一段內(nèi)存嘛,數(shù)組在全局區(qū)就是這么表示的!

數(shù)組與堆區(qū)

來(lái)段代碼:

void array_on_heap() {
int* arr = (int*)malloc(sizeof(int) * 6);
arr[0] = 100;
arr[1] = 200;
arr[2] = 300;
arr[3] = 400;
arr[4] = 500;
arr[5] = 600;

int a = arr[0];
}

使用gdb加斷點(diǎn)在int a = arr[0];這行代碼,然后打印數(shù)組arr的地址:

(gdb) p arr
$20 = (int *) 0x602010

注意0x602010這個(gè)地址,這個(gè)地址和剛才的全局?jǐn)?shù)組global_array的地址0x601050比較接近,因?yàn)槎褏^(qū)和全局區(qū)挨得比較近,可以再回過頭看一下開局那張圖。

然后我們同樣使用x命令查看這個(gè)區(qū)域的內(nèi)存內(nèi)容:

(gdb)  x/6wd 0x602010
0x602010: 100 200 300 400
0x602020: 500 600

依然不出我們所料,這個(gè)區(qū)域保存的正是數(shù)組的值。

圖片

這就是C語(yǔ)言中所謂的數(shù)組了,無(wú)非就是從 0x602010到 0x602028這一段內(nèi)存嘛,數(shù)組在堆區(qū)就是這么表示的!

現(xiàn)在你應(yīng)該明白了吧,C語(yǔ)言中所謂的數(shù)組是怎么表示的?很簡(jiǎn)單,其實(shí)也沒啥表示,無(wú)非就是內(nèi)存中一段連續(xù)的空間,僅此而已。

希望這篇文章對(duì)大家理解C語(yǔ)言中的數(shù)組有所幫助。

責(zé)任編輯:趙寧寧 來(lái)源: 碼農(nóng)的荒島求生
相關(guān)推薦

2018-02-24 12:17:56

C程序內(nèi)存方式

2024-01-18 08:38:34

.NET數(shù)組內(nèi)存管理

2018-08-24 10:16:23

內(nèi)存浮點(diǎn)數(shù)存儲(chǔ)

2010-01-26 10:01:17

學(xué)習(xí)C++

2019-01-07 10:24:41

2021-12-16 06:52:33

C語(yǔ)言內(nèi)存分配

2021-12-22 06:56:07

STM32C語(yǔ)言內(nèi)存

2011-07-05 16:57:53

C語(yǔ)言

2023-10-18 13:25:00

操作系統(tǒng)進(jìn)程

2021-12-30 11:26:31

語(yǔ)言編譯器腳本

2024-10-11 10:00:20

2017-09-15 16:02:15

函數(shù)代碼CPU

2023-12-21 11:46:48

C語(yǔ)言柔性數(shù)組開發(fā)

2010-01-25 10:25:19

C++變量

2010-01-12 10:50:59

學(xué)習(xí)C++

2011-07-14 22:25:36

2020-10-19 09:34:04

C語(yǔ)言內(nèi)存錯(cuò)誤編程語(yǔ)言

2022-01-13 10:30:21

C語(yǔ)言內(nèi)存動(dòng)態(tài)

2025-04-03 10:39:56

2013-08-05 15:44:36

C語(yǔ)言基礎(chǔ)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)