日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

总结:数组名和指针完全是两码事

發(fā)布時(shí)間:2025/3/17 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 总结:数组名和指针完全是两码事 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 大家經(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]:
指針下標(biāo)訪問時(shí)p_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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。