前言:
- (void)viewDidLoad {
[super viewDidLoad];
int arrayName[4] = {10,20,30,40};
int *p = (int *)(&arrayName + 1);
NSLog(@"%d", *(p - 1));
}
很多小伙伴都很面熟吧,差不多10個(gè)人有7個(gè)人都不知道這個(gè)輸出的結(jié)果是什么吧,或許有知道答案的,但是僅僅知道答案,心里還是一頭霧水。如果你真的不會(huì)那就請認(rèn)真看完本文學(xué)習(xí)一下吧!
錯(cuò)誤想法:
有的人認(rèn)為
NSLog(@"%d", *(&arrayName + 1 - 1));
加1減1不就是抵消了么,那肯定是訪問數(shù)組首地址,那打印的值肯定是 10,看起來是通的(引用宋小寶小品海參炒面一句話:湯面沒給錢,湯面用炒面換得給什么錢?炒面也沒給錢啊,炒面沒吃給什么錢?)但是含義是不一樣的。
指針是如何加減運(yùn)算:
- int *p 的解釋:將來的指針是指向int類型
指針p + 1 說明內(nèi)存地址會(huì)加上4個(gè)字節(jié)(因?yàn)槭莍nt占4個(gè)字節(jié))
如果是 double *p 指針p + 1內(nèi)存地址會(huì)加上8個(gè)字節(jié)(因?yàn)槭莇ouble占8個(gè)字節(jié))
- 通過上述解釋我們得出一個(gè)公式:
指針p + n = p當(dāng)前的地址值 + n *指向類型所占用的字節(jié)數(shù)
指針p - n = p當(dāng)前的地址值 - n * 指向類型所占用的字節(jié)數(shù)
數(shù)組與指針:
int arrayName[4] = {10, 20, 30, 40};
上面的數(shù)組占16個(gè)字節(jié)(原因:每個(gè)int類型占4個(gè)字節(jié),這個(gè)數(shù)組有4個(gè)int類型,所以占16個(gè)字節(jié))
arrayName就是數(shù)組名
數(shù)組名 :表示數(shù)組首元素的地址,相當(dāng)于一個(gè)指向數(shù)組首元素的指針
相信你已經(jīng)有點(diǎn)蒙圈了,我們在進(jìn)一步解釋一下:
NSLog(@"%p %p", arrayName, arrayName + 1);
NSLog(@"%p %p", &arrayName, &arrayName + 1);
看看下面的輸出結(jié)果:
2016-07-17 21:46:00.845 數(shù)組與指針筆試題[1861:196315] 0x7fff53a7ca30 0x7fff53a7ca34
2016-07-17 21:46:00.846 數(shù)組與指針筆試題[1861:196315] 0x7fff53a7ca30 0x7fff53a7ca40
我們從輸出的結(jié)果可以知道arrayName 與 &arrayName的地址是相同的,而(arrayName + 1) 與 (&arrayName + 1)輸出的結(jié)果不一樣.
下面就來解釋為什么是這樣的結(jié)果:
1. arrayName 與 &arrayName
arrayName 是數(shù)組名,所以打印出來是數(shù)組首元素的地址
&arrayName 含義就是數(shù)組的地址(等價(jià)于指向arrayName數(shù)組的指針),因?yàn)闆]增加1,所以數(shù)組的地址就是數(shù)組首元素的地址所以 arrayName <->&arrayName 打印出的地址是一樣的
2.(arrayName + 1) 與 (&arrayName + 1)
(arrayName + 1)通過上述解釋我們知道(arrayName + 1)指針是指向int類型,所以內(nèi)存地址會(huì)加上4個(gè)字節(jié)
(&arrayName + 1)我們知道&arrayName是數(shù)組的地址(等價(jià)于指向arrayName數(shù)組的指針) 因?yàn)樵黾?,這個(gè)數(shù)組總共占16個(gè)字節(jié),所以內(nèi)存地址會(huì)加上16個(gè)字節(jié)
最后答案解析
int arrayName[4] = {10, 20, 30, 40};
/**
1.(&arrayName + 1):&arrayName是數(shù)組的地址(等價(jià)于指向arrayName數(shù)組的指針)
2.增加 1 會(huì)往后移動(dòng)16個(gè)字節(jié),開始是4個(gè)字節(jié)的位置,移動(dòng)后就是16個(gè)字節(jié)后面的位置(也就是目前位置是20個(gè)字節(jié))
3.最后又賦值給,int類型的指針p(int類型占4個(gè)字節(jié))
4.所以(p - 1)就是減去4個(gè)字節(jié),變成為16個(gè)字節(jié)的位置,輸出的*(p - 1)值為40
*/
int *p = (int *)(&arrayName + 1);
NSLog(@"%d", *(p - 1));//輸出結(jié)果為 40