一道數(shù)組指針題搞清楚x86內(nèi)存

后續(xù)文章也同時(shí)遷移至個(gè)人博客 http://kimihe.com/

參考: iOS 最詳細(xì)的解析(數(shù)組與指針)筆試題,并做了改進(jìn)。

引題

先來看一下這道題目,如下代碼的輸出結(jié)果是什么?

short arrayName[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int *q = (int *)(&arrayName+1);
printf("*(q-2):%d\n", *(q-2));

在看后文的解釋前,不妨自己思考一下。

.
.
.
.
.
.
.
.
.
.
.
.
.

好了,相信你已經(jīng)思考過了,我們來揭曉結(jié)果,結(jié)果是令人匪夷所思的458758,答對(duì)了嗎?也許你會(huì)有疑惑,那么請(qǐng)看下面的注解,在其中增加了些許解釋代碼,并在關(guān)鍵代碼后有注釋。

詳細(xì)注釋解答:

short arrayName[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 0; i < 10; i++) {
    printf("arr%d addr:%p\n", i, arrayName+i);
}
//&arratName是short(*)[10]類型
short *sp1 = (short *)&arrayName+2; //short(*)[10]先轉(zhuǎn)short*,再移動(dòng)2個(gè)short*位(4B)
short *sp2 = (short *)(&arrayName+2);//short(*)[10]先移動(dòng)2個(gè)數(shù)組位(20個(gè)short*: 40B->0x28),再轉(zhuǎn)short*型
printf("sp1:%p\nsp2:%p\n", sp1, sp2);

short *p = (short *)(&arrayName+1);//short(*)[10]先移動(dòng)1個(gè)數(shù)組位(10個(gè)short*: 20B->0x14),再轉(zhuǎn)short*型
int *q = (int *)(&arrayName+1);//short(*)[10]先移動(dòng)1個(gè)數(shù)組位(10個(gè)short*: 20B->0x14),再轉(zhuǎn)int*型
printf("p: %p\nq: %p\n", p, q);
printf("p-2:%p\nq-2:%p\n", p-2, q-2);

//q-2:移動(dòng)2個(gè)short*(4B), p-2:移動(dòng)2個(gè)int*(8B)
//x86是小端字節(jié)序: 0x0007 0006 -> 7*256*256+6=458758
printf("*(p-2):%d\n*(q-2):%d", *(p-2), *(q-2));

內(nèi)存地址分配圖:

內(nèi)存地址分配圖.png

重點(diǎn):

  • 字節(jié)序
  • 內(nèi)存地址分配
  • 類型轉(zhuǎn)換

補(bǔ)充

最后我們通過匯編,來深入理解一下如下幾行代碼的含義:

int *p = NULL;
p = (int *)&arrayName;
p = (int *)(&arrayName+1);

對(duì)應(yīng)的匯編分別為:

匯編代碼.png

如圖三個(gè)紅圈,這邊是AT&T的匯編格式,我們還是以更好看的intel的樣式來說明:

  • 第一個(gè)紅圈,左邊的$0x00立即數(shù)賦給[rbp-0x28]這個(gè)內(nèi)存地址,0x00就是NULL的值,而[rbp-0x28]內(nèi)存地址就是指針p的值(不是*p)。
  • 第二個(gè)紅圈,rcx寄存器中含有arrayName數(shù)組的首地址(注意:arrayName+0&arrayName取得的地址是相同的),賦給rdx;rdx在把它賦給[rbp-0x28],即賦給指針p。
  • 第三個(gè)紅圈,第一句中,$0x14立即數(shù)就是十進(jìn)制的20,表明10個(gè)short*型,因?yàn)槊總€(gè)short *占2B。$0x14賦給rcx寄存器,rcx再賦給指針p,最終導(dǎo)致前文所說的,所謂移動(dòng)整個(gè)數(shù)組位,從第0個(gè)元素移到了第11個(gè)元素(雖然數(shù)組并沒有第11個(gè)元素,但位置的移動(dòng)可以這樣理解)。

That's all. Thanks for reading.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,615評(píng)論 3 44
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場景。SDWebImage的原...
    LZM輪回閱讀 2,127評(píng)論 0 12
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,154評(píng)論 25 708
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,844評(píng)論 0 4
  • (原文:http://codejust.top/ubuntu14-04-install-elasticsearch...
    codjust閱讀 6,700評(píng)論 6 12

友情鏈接更多精彩內(nèi)容