总结:数组名和指针完全是两码事
? 大家經(jīng)常接觸到諸如:“數(shù)組名可以當(dāng)作指向數(shù)組首元素的指針用”、“指針可以用數(shù)組下標(biāo)方式進(jìn)行訪問”這些事實(shí),所以數(shù)組和指針的概念經(jīng)常被混淆,其實(shí)數(shù)組和指針是完全不同的兩種類型,下面本文分析一些常常被人們忽略的事實(shí)。
1.數(shù)組和指針是兩種完全不同的類型
int arr[10] = {0,1,2,3,4,5,6,7,8,9}; int *p_arr = arr;? 數(shù)組名arr代表著內(nèi)存中有一塊連續(xù)的區(qū)域,這個(gè)區(qū)域存儲(chǔ)了10個(gè)int變量,它的大小在編譯時(shí)已經(jīng)確定(動(dòng)態(tài)數(shù)組除外)。
? 指針名p_arr代表著內(nèi)存中的可以一個(gè)塊,這個(gè)塊的大小為足夠表示地址的大小,這個(gè)塊的內(nèi)容是一個(gè)int變量所在的地址。
在內(nèi)存中是這個(gè)樣子:
Object Address 0x00 0x01 0x02 0x03 ------ ------- ----------------------arr 0x10008000 0x00 0x00 0x00 0x010x10008004 0x00 0x02 0x00 0x030x10008008 0x00 0x04 0x00 0x050x1000800c 0x00 0x06 0x00 0x070x10008010 0x00 0x08 0x00 0x09parr 0x10008014 0x10 0x00 0x80 0x00【應(yīng)用】 ?
這就解釋了讓人困擾的sizeof問題:
? 為什么sizeof(arr)返回?cái)?shù)組總大小,sizeof(p_arr)只返回指針大小?
? 答:arr代表數(shù)組這塊內(nèi)存區(qū)域,編譯后其大小就是固定的已知的,所以sizeof可以讀出其大小。
2.數(shù)組和指針都可通過下標(biāo)訪問,但訪問途徑有所不同。
? 上面的例子中,用arr[i]和p_arr[i]的效果完全一樣。但是內(nèi)部實(shí)現(xiàn)有所差別!
| 數(shù)組下標(biāo)訪問時(shí)arr[i]: |
| |
| arr對(duì)應(yīng)編譯器符號(hào)表有個(gè)地址add0 運(yùn)行時(shí)步驟一:取i的值與add0相加得add1=add0+i 運(yùn)行時(shí)步驟二:取add1的內(nèi)容 | p_arr對(duì)應(yīng)編譯器符號(hào)表有個(gè)地址add0 運(yùn)行時(shí)步驟一:取add0的內(nèi)容add1=(add0) 運(yùn)行時(shí)步驟一:取i的值與add1相加得add2=add1+i 運(yùn)行時(shí)步驟二:取地址add2的內(nèi)容 |
可見指針下標(biāo)訪問方式比數(shù)組多一次取地址步驟,即指針是間接訪問、數(shù)組時(shí)直接訪問。
【應(yīng)用】
解釋了:1).如果arr在一個(gè)文件中定義為數(shù)組,把它再另一個(gè)文件中聲明為指針后,進(jìn)行訪問會(huì)錯(cuò)誤。2).如果p在一個(gè)文件中定義為指針,把它在另一個(gè)文件中聲明為數(shù)組后,訪問仍會(huì)錯(cuò)誤。
?
3.數(shù)組和指針下標(biāo)符號(hào)的本質(zhì)
?
定義:a[i]?is identical to?(*((a)+(i)))
?
當(dāng)數(shù)組下標(biāo)訪問時(shí)arr[i],其實(shí)是這樣:(*(arr+i))。arr+i運(yùn)算時(shí)數(shù)組名arr就轉(zhuǎn)換為了指向首元素的指針,所以會(huì)和指針下標(biāo)有同樣的效果。
?
這個(gè)定義也意味著:a[i]與i[a]其實(shí)是等價(jià)的,大家可以實(shí)驗(yàn)。
?
另外,對(duì)起始地址執(zhí)行加法之前,編譯器負(fù)責(zé)計(jì)算每次增加的步長。
如int *的指針p,p+1時(shí)會(huì)執(zhí)行地址+4而不是+1。
所以,每種指針必須有一種類型的原因是:編譯器需要知道 1)對(duì)指針解引用操作時(shí)應(yīng)該取幾個(gè)字節(jié) 2)下標(biāo)的步長應(yīng)該取幾個(gè)字節(jié)
?
?
4.數(shù)組名不能轉(zhuǎn)換為指針的情況
數(shù)組名在許多場(chǎng)合會(huì)自動(dòng)轉(zhuǎn)換為指向數(shù)組首元素的指針(函數(shù)傳參、賦值給指針、表達(dá)式),但有些場(chǎng)合不會(huì)發(fā)生轉(zhuǎn)換。
我所知道的有兩種情況:sizeof操作符和&取地址操作符。
sizeof上面已經(jīng)講過。
我們看看arr和&arr的差別:
1 int arr[10] = {0,1,2,3,4,5,6,7,8,9}; 2 int *p = arr; 3 int (*ap)[10] = &arr; 4 5 printf("before: arr = %p, p = %p, ap = %p\n", (void *) arr, (void *) p, (void *) ap); 6 p++; 7 ap++; 8 printf("after: arr = %p, p = %p, ap = %p\n", (void *) arr, (void *) p, (void *) ap);運(yùn)行結(jié)果:
before: ?arr = 0xbfbb96a0, p = 0xbfbb96a0, ap = 0xbfbb96a0
after: ? ?arr = 0xbfbb96a0, p = 0xbfbb96a4, ap = 0xbfbb96c8
可以看出ap指向的是整個(gè)數(shù)組,當(dāng)ap++后指針往后移動(dòng)了40個(gè)字節(jié)。
?
?5.指針和數(shù)組在“定義時(shí)初始化”的不同
定義指針時(shí),除了字符串常量的情況,編譯器不為指針?biāo)赶虻膶?duì)象分配空間,只分配指針本身的空間。
char *p = "abcde"; //正確,但這個(gè)字符串存是只讀的int *p = 5; //錯(cuò)誤,不能給除了字符串以為的常量分配空間定義數(shù)組時(shí)不存在這個(gè)問題。
?
6.數(shù)組名是不可修改的左值,指針是可修改的左值
左值:代表地址,表示存儲(chǔ)結(jié)果的地方,在編譯時(shí)可知。
右值:代表地址的內(nèi)容,直到運(yùn)行時(shí)才知。
數(shù)組名用于確定對(duì)象在內(nèi)存中的位置,是左值,可是不能被賦值。如:
?
int arr1[10], arr2[10]; main() {int *p;arr1 = arr2; //錯(cuò)誤,數(shù)組名不能被賦值p = arr1; //正確,指針可以被賦值 }?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/renzhe688/p/3365894.html
總結(jié)
以上是生活随笔為你收集整理的总结:数组名和指针完全是两码事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bitmap 位图
- 下一篇: 学习笔记-记ActiveMQ学习摘录与心