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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

数组指针和指针数组的区别(1)

發(fā)布時(shí)間:2023/12/18 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数组指针和指针数组的区别(1) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、指針數(shù)組和數(shù)組指針的內(nèi)存布局

初學(xué)者總是分不出指針數(shù)組與數(shù)組指針的區(qū)別。其實(shí)很好理解:
指針數(shù)組:首先它是一個(gè)數(shù)組,數(shù)組的元素都是指針,數(shù)組占多少個(gè)字節(jié)由數(shù)組本身決定。它是“儲(chǔ)存指針的數(shù)組”的簡(jiǎn)稱。
數(shù)組指針:首先它是一個(gè)指針,它指向一個(gè)數(shù)組。在32 位系統(tǒng)下永遠(yuǎn)是占4 個(gè)字節(jié),至于它指向的數(shù)組占多少字節(jié),不知道。它是“指向數(shù)組的指針”的簡(jiǎn)稱。

下面到底哪個(gè)是數(shù)組指針,哪個(gè)是指針數(shù)組呢:
A)
int *p1[10];
B)
int (*p2)[10];
每次上課問(wèn)這個(gè)問(wèn)題,總有弄不清楚的。這里需要明白一個(gè)符號(hào)之間的優(yōu)先級(jí)問(wèn)題。

“[]”的優(yōu)先級(jí)比“*”要高。p1 先與“[]”結(jié)合,構(gòu)成一個(gè)數(shù)組的定義,數(shù)組名為p1,int *修飾的是數(shù)組的內(nèi)容,即數(shù)組的每個(gè)元素。那現(xiàn)在我們清楚,這是一個(gè)數(shù)組,其包含10 個(gè)指向int 類型數(shù)據(jù)的指針,即指針數(shù)組。至于p2 就更好理解了,在這里“()”的優(yōu)先級(jí)比“[]”高,“*”號(hào)和p2 構(gòu)成一個(gè)指針的定義,指針變量名為p2,int 修飾的是數(shù)組的內(nèi)容,即數(shù)組的每個(gè)元素。數(shù)組在這里并沒(méi)有名字,是個(gè)匿名數(shù)組。那現(xiàn)在我們清楚p2 是一個(gè)指針,它指向一個(gè)包含10 個(gè)int 類型數(shù)據(jù)的數(shù)組,即數(shù)組指針。我們可以借助下面的圖加深理解:

二、int (*)[10] p2-----也許應(yīng)該這么定義數(shù)組指針

這里有個(gè)有意思的話題值得探討一下:平時(shí)我們定義指針不都是在數(shù)據(jù)類型后面加上指針變量名么?這個(gè)指針p2 的定義怎么不是按照這個(gè)語(yǔ)法來(lái)定義的呢?也許我們應(yīng)該這樣來(lái)定義p2:
? ?int (*)[10] p2;
int (*)[10]是指針類型,p2 是指針變量。這樣看起來(lái)的確不錯(cuò),不過(guò)就是樣子有些別扭。其實(shí)數(shù)組指針的原型確實(shí)就是這樣子的,只不過(guò)為了方便與好看把指針變量p2 前移了而已。你私下完全可以這么理解這點(diǎn)。雖然編譯器不這么想。^_^

三、再論a 和&a 之間的區(qū)別

既然這樣,那問(wèn)題就來(lái)了。前面我們講過(guò)a 和&a 之間的區(qū)別,現(xiàn)在再來(lái)看看下面的代碼:
int main()
{
? ?char a[5]={'A','B','C','D'};
? ?char (*p3)[5] = &a;
? ?char (*p4)[5] = a;
? ?return 0;
}
上面對(duì)p3 和p4 的使用,哪個(gè)正確呢?p3+1 的值會(huì)是什么?p4+1 的值又會(huì)是什么?毫無(wú)疑問(wèn),p3 和p4 都是數(shù)組指針,指向的是整個(gè)數(shù)組。&a 是整個(gè)數(shù)組的首地址,a是數(shù)組首元素的首地址,其值相同但意義不同。在C 語(yǔ)言里,賦值符號(hào)“=”號(hào)兩邊的數(shù)據(jù)類型必須是相同的,如果不同需要顯示或隱式的類型轉(zhuǎn)換。p3 這個(gè)定義的“=”號(hào)兩邊的數(shù)據(jù)類型完全一致,而p4 這個(gè)定義的“=”號(hào)兩邊的數(shù)據(jù)類型就不一致了。左邊的類型是指向整個(gè)數(shù)組的指針,右邊的數(shù)據(jù)類型是指向單個(gè)字符的指針。在Visual C++6.0 上給出如下警告:
? ?warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。
還好,這里雖然給出了警告,但由于&a 和a 的值一樣,而變量作為右值時(shí)編譯器只是取變量的值,所以運(yùn)行并沒(méi)有什么問(wèn)題。不過(guò)我仍然警告你別這么用。

既然現(xiàn)在清楚了p3 和p4 都是指向整個(gè)數(shù)組的,那p3+1 和p4+1 的值就很好理解了。

但是如果修改一下代碼,會(huì)有什么問(wèn)題?p3+1 和p4+1 的值又是多少呢?
int main()
{
? ?char a[5]={'A','B','C','D'};
? ?char (*p3)[3] = &a;
? ?char (*p4)[3] = a;
? ?return 0;
}

甚至還可以把代碼再修改:
int main()
{
? ?char a[5]={'A','B','C','D'};
? ?char (*p3)[10] = &a;
? ?char (*p4)[10] = a;
? ?return 0;
}
這個(gè)時(shí)候又會(huì)有什么樣的問(wèn)題?p3+1 和p4+1 的值又是多少?

上述幾個(gè)問(wèn)題,希望讀者能仔細(xì)考慮考慮。

四、地址的強(qiáng)制轉(zhuǎn)換

先看下面這個(gè)例子:
struct Test
{
? ?int Num;
? ?char *pcName;
? ?short sDate;
? ?char cha[2];
? ?short sBa[4];
}*p;

假設(shè)p 的值為0x100000。如下表表達(dá)式的值分別為多少?
? ?p + 0x1 = 0x___ ?
? ?(unsigned long)p + 0x1 = 0x___?
? ?(unsigned int*)p + 0x1 = 0x___?
我相信會(huì)有很多人一開始沒(méi)看明白這個(gè)問(wèn)題是什么意思。其實(shí)我們?cè)僮屑?xì)看看,這個(gè)知識(shí)點(diǎn)似曾相識(shí)。一個(gè)指針變量與一個(gè)整數(shù)相加減,到底該怎么解析呢?

還記得前面我們的表達(dá)式“a+1”與“&a+1”之間的區(qū)別嗎?其實(shí)這里也一樣。指針變量與一個(gè)整數(shù)相加減并不是用指針變量里的地址直接加減這個(gè)整數(shù)。這個(gè)整數(shù)的單位不是byte 而是元素的個(gè)數(shù)。所以:p + 0x1 的值為0x100000+sizof(Test)*0x1。至于此結(jié)構(gòu)體的大小為20byte,前面的章節(jié)已經(jīng)詳細(xì)講解過(guò)。所以p +0x1 的值為:0x100014。

(unsigned long)p + 0x1 的值呢?這里涉及到強(qiáng)制轉(zhuǎn)換,將指針變量p 保存的值強(qiáng)制轉(zhuǎn)換成無(wú)符號(hào)的長(zhǎng)整型數(shù)。任何數(shù)值一旦被強(qiáng)制轉(zhuǎn)換,其類型就改變了。所以這個(gè)表達(dá)式其實(shí)就是一個(gè)無(wú)符號(hào)的長(zhǎng)整型數(shù)加上另一個(gè)整數(shù)。所以其值為:0x100001。

(unsigned int*)p + 0x1 的值呢?這里的p 被強(qiáng)制轉(zhuǎn)換成一個(gè)指向無(wú)符號(hào)整型的指針。所以其值為:0x100000+sizof(unsigned int)*0x1,等于0x100004。

上面這個(gè)問(wèn)題似乎還沒(méi)啥技術(shù)含量,下面就來(lái)個(gè)有技術(shù)含量的:在x86 系統(tǒng)下,其值為多少?
intmain()
{
? ?int a[4]={1,2,3,4};
? ?int *ptr1=(int *)(&a+1);
? ?int *ptr2=(int *)((int)a+1);
? ?printf("%x,%x",ptr1[-1],*ptr2);
? ?return 0;
}
這是我講課時(shí)一個(gè)學(xué)生問(wèn)我的題,他在網(wǎng)上看到的,據(jù)說(shuō)難倒了n 個(gè)人。我看題之后告訴他,這些人肯定不懂匯編,一個(gè)懂匯編的人,這種題實(shí)在是小case。下面就來(lái)分析分析這個(gè)問(wèn)題:

根據(jù)上面的講解,&a+1 與a+1 的區(qū)別已經(jīng)清楚。

ptr1:將&a+1 的值強(qiáng)制轉(zhuǎn)換成int*類型,賦值給int* 類型的變量ptr,ptr1 肯定指到數(shù)組a 的下一個(gè)int 類型數(shù)據(jù)了。ptr1[-1]被解析成*(ptr1-1),即ptr1 往后退4 個(gè)byte。所以其值為0x4。
ptr2:按照上面的講解,(int)a+1 的值是元素a[0]的第二個(gè)字節(jié)的地址。然后把這個(gè)地址強(qiáng)制轉(zhuǎn)換成int*類型的值賦給ptr2,也就是說(shuō)*ptr2 的值應(yīng)該為元素a[0]的第二個(gè)字節(jié)開始的連續(xù)4 個(gè)byte 的內(nèi)容。

其內(nèi)存布局如下圖:

好,問(wèn)題就來(lái)了,這連續(xù)4 個(gè)byte 里到底存了什么東西呢?也就是說(shuō)元素a[0],a[1]里面的值到底怎么存儲(chǔ)的。這就涉及到系統(tǒng)的大小端模式了,如果懂匯編的話,這根本就不是問(wèn)題。既然不知道當(dāng)前系統(tǒng)是什么模式,那就得想辦法測(cè)試。大小端模式與測(cè)試的方法在第一章講解union 關(guān)鍵字時(shí)已經(jīng)詳細(xì)討論過(guò)了,請(qǐng)翻到彼處參看,這里就不再詳述。我們可以用下面這個(gè)函數(shù)來(lái)測(cè)試當(dāng)前系統(tǒng)的模式。
int checkSystem( )
{
? ?union check
? ?{
? ? ? int i;
? ? ?char ch;
? ?} c;
? ?c.i = 1;
? ?return (c.ch ==1);
}
如果當(dāng)前系統(tǒng)為大端模式這個(gè)函數(shù)返回0;如果為小端模式,函數(shù)返回1。也就是說(shuō)如果此函數(shù)的返回值為1 的話,*ptr2 的值為0x2000000。如果此函數(shù)的返回值為0 的話,*ptr2 的值為0x100。

出處:http://see.xidian.edu.cn/cpp/html/476.html

2018-12-06

轉(zhuǎn)載于:https://www.cnblogs.com/DWVictor/p/10074967.html

總結(jié)

以上是生活随笔為你收集整理的数组指针和指针数组的区别(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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