一個(gè)有10個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù)的
int *p[10];
上面這個(gè)比較好理解,平時(shí)用得也比較多,問題是下面....
如果一個(gè)數(shù)組如下定義:
int a[10];
那么找個(gè)指針指向它只要int *p = a;就定義完成了...可以理解為“一個(gè)指向有10個(gè)整形數(shù)組的指針”
同樣,有如下定義:
int (*p)[10];
該定義含義也是“一個(gè)指向有10個(gè)整型數(shù)數(shù)組的指針”,這個(gè)定義有點(diǎn)讓我莫名其妙...寫了那么多的C我還真沒見過誰這么用的,因此想問個(gè)明白
請教高人指點(diǎn)...
網(wǎng)友評論:呵呵,
int A[10];
int (*p)[10];
p = A;
我測試恰恰是keil,vc,IAR通不過。
picc卻能通過。
p = &A,
各種編譯器總是沒有問題。
網(wǎng)友評論:int A[10];// 實(shí)際分配一個(gè)含10個(gè)int單元的數(shù)組
int (*p)[10];// 定義一個(gè)指針,注意尚未有實(shí)際空間被指定
同意上面差別。那么下面概念/寫法一定是對的:[ ]左傍指針——[ ]左邊必是指針,所以:
*P是指針,P[ ]是指針,A是指針,(*P)也是指針。所以:
*P=A ;——> P=&A; /P=A;// 概念上一樣。既然編譯結(jié)果唯一,自然2種寫法都可以。
網(wǎng)友評論:感覺和函數(shù)指針類似
網(wǎng)友評論:有意思~~
網(wǎng)友評論:
謝謝大家的熱心幫助!!
最近本人主要在搞一些鉆牛角尖問題...主要因?yàn)橛行┣拜叺某绦驅(qū)嵲谔⒅丶记桑约簺]點(diǎn)技巧就沒法見招拆招~~
比如...有人偏偏就喜歡用下面這種語句:
(*(void(*)(void))0)();
還有的人風(fēng)格是不錯(cuò),就是...一個(gè)變量union套struct套來套去,1~6層這也沒什么,10幾層...這就有點(diǎn)什么了,比如A.B.C.D.E.F.G.H.I.J = 0;(把前面字母換成名字超長的類型)一個(gè)變量上百個(gè)字符,這真是非常雷人啊...
這個(gè)指針問題我基本弄懂怎么回事了...現(xiàn)在試著用自己的語言組織一下..
比如有這么個(gè)數(shù)組定義:
int a[10];
int *p;
p = a;
這個(gè)就是最常用的類型,隨后*p便代表a[0],也可寫成p[0],然后一旦執(zhí)行了p++;之后,*p就代表a[1],p[1]等效為*(p+1)指的就是a[2]
如果擴(kuò)展成二維數(shù)組,又假設(shè)有如下定義:
int b[10][10];
那么本質(zhì)上是由10個(gè)一維數(shù)組組成,這10個(gè)數(shù)組的首地址為b[0]~b[9],這里的b代表的就是b[0]這個(gè)【首地址】的【地址】,現(xiàn)在有如下定義
int (*p)[10];
那么只要如此賦值:
p = &b[0];或者p = b;
那么(*(p + 1))[5];代表的就是b[1][5],這時(shí)候用p[1][5]來描述也是一回事..
又是同理,再次假設(shè)一個(gè)定義:
int c[10][10][10];
int (*p)[10][10];
int (*q)[10];
int *r;
如此賦值:p = &c[0];或者p = c;
那么(*(p + 5))[2][6]和c[5][2][6]等效
繼續(xù):q = &c[0][0]; 或者q = c[0];
那么(*(q + 12))[3]和c[1][2][3]等效
再來:r = &c[0][0][0];或者r = c[0][0];
那么*(r + 789)和c[7][8][9]等效......
這樣的理解應(yīng)該沒問題了把?
網(wǎng)友評論:指針數(shù)組:即一個(gè)由若干指針構(gòu)成的數(shù)組。
例:int *p[10] //定義了一個(gè)數(shù)組,該數(shù)組的元素為指向整型數(shù)據(jù)指針p。
數(shù)組指針:即一個(gè)指向數(shù)組的指針。
例:int (*p)[10] //定義了一個(gè)指針,該指針指向一個(gè)由十個(gè)元素組成的數(shù)組。
網(wǎng)友評論:我的keil通不過,有error惡
網(wǎng)友評論:我keil C51 編譯通過.
網(wǎng)友評論:[]這個(gè)符號就是人強(qiáng)行規(guī)定的。 比較難以理解。只能死記硬背。
*這個(gè)符號是客觀存在的。
API--------------控件 等價(jià)于 *-----------[]
個(gè)人觀點(diǎn)
網(wǎng)友評論:struct搞個(gè)十幾層很正常,編過復(fù)雜點(diǎn)的程序你就知道必要性了,不過人家不會A.B.C.D.E.F……這么用,
肯定函數(shù)也是一個(gè)套一個(gè)的,一層函數(shù)對應(yīng)一層struct,數(shù)據(jù)則通過指針傳遞
網(wǎng)友評論:我一會用gcc試試.
各位前輩有講講為啥 p=A和p=&A一樣啊. 這個(gè)真不知道. A作為一個(gè)地址, 也應(yīng)該存在
內(nèi)存的, 有實(shí)體的, &A應(yīng)該就是存放這個(gè)地址的內(nèi)存地址啊. A==&A這個(gè)是咋回事? 難道指針變臉都在內(nèi)存無實(shí)體???????
還有LS的"struct搞個(gè)十幾層" 這個(gè)也太夸張了吧.........超大型數(shù)據(jù)庫上這個(gè)量還有可能.
網(wǎng)友評論:個(gè)人看法:最重要的一點(diǎn):A是常量指針!它的地址是一個(gè)常數(shù)。一個(gè)常數(shù)是包含在程序里的吧?例如:MOV A,#55H; 這個(gè)55H是跟著語句跑的吧,它有地址特征嗎?它需要間接尋址嗎?
網(wǎng)友評論:int *p[10];
和int (*p)[10]
定義不同。
最大的區(qū)別應(yīng)該是在做指針的加法時(shí)就很明顯吧。即p++;
如果是 int *p[10]; 則p++,p會增加2
如果是 int (*p)[10],則p++,p會增加20;
呵呵,我覺得應(yīng)該是這樣吧。主要是告訴編譯器指針的類型。
網(wǎng)友評論:
這么熱鬧啊!我前段時(shí)間也用了這個(gè)數(shù)組,不玩虛的,直接舉例。
unsigned charu8_sample1[3]={1,2,3};
unsigned char u8_sample2[3]={3,2,1};
unsigned char *p_u8_sampleX[2]={u8_sample1,u8_sample2};
于是
*p_u8_sampleX[0] = u8_sample1[0];
unsigned char u8_sampleXY[2][3]={{1,2,3}{3,2,1}};
unsigned char(*p)[3] = u8_sampleXY;
*p_u8_sampleXY[0]= u8_sampleXY[0][0]=1;
*(p_u8_sampleXY+1)[2]= u8_sampleXY[1][2]=1;
*(*(p_u8_sampleXY+1)+1)= u8_sampleXY[1][1]=2;
網(wǎng)友評論:*p_u8_sampleXY[0]= u8_sampleXY[0][0]=1;
*(p_u8_sampleXY+1)[2]= u8_sampleXY[1][2]=1;
*(*(p_u8_sampleXY+1)+1)= u8_sampleXY[1][1]=2;
寫清楚呀:
*u8_sampleXY[0]= u8_sampleXY[0][0]=1;
*(u8_sampleXY+1)[2]= u8_sampleXY[1][2]=1;
*(*(u8_sampleXY+1)+1)= u8_sampleXY[1][1]=2;
網(wǎng)友評論:36#
對地址進(jìn)行取地址 等于地址本身keil下。
設(shè)地址為ADDRESS
那么ADDRESS = &&&&&&&&&&&&&&&&&&&&ADDRESS。
這就是編譯器編寫的人隨便弄的。
網(wǎng)友評論:gcc 測試結(jié)果如下:
程序1:
int main(void)
{
int A[10];
int (*p)[10];
p = A;
(*p)[1] = 1;
(*p)[2] = 2;
return 0;
}
復(fù)制代碼$ gcc -o test test.c -Wall
test.c: In function ‘main’:
test.c:5: warning: assignment from incompatible pointer type
能編譯成功, 正常運(yùn)行,但有W。
程序2,
int main(void)
{
int A[10];
int (*p)[10];
p = &A;
(*p)[1] = 1;
(*p)[2] = 2;
return 0;
}
復(fù)制代碼$ gcc -o test test.c -Wall
無任何警告成功。
網(wǎng)友評論:那么經(jīng)我測試, 這個(gè)
p==&p
&p==&&p
&&p==&&&p
確實(shí)成立,
這個(gè)不知道是什么原因。
恐怕不是 “這就是編譯器編寫的人隨便弄的“這么簡單吧。
簡單的現(xiàn)象總有背后的解釋。哪位大俠能解釋下。我google了下沒有查到端倪。
網(wǎng)友評論:數(shù)組名在C中,有的時(shí)候可以認(rèn)為它就是代表著數(shù)組首地址。
這還要做什么解釋?
網(wǎng)友評論:
定義一個(gè)數(shù)組int A[10],A是一個(gè)常量,類型是int *,一個(gè)常量前加“&”并不是對該常量取地址。&A也是一個(gè)常量,和并且“A”在數(shù)值上是相同的,但"&A"的類型是int (*)[10],所以在42樓的第一種寫**有警告。
同理,如果定義一個(gè)二維數(shù)組int B[1][10],那么B[0]是常量,類型是int *,&B[0]也是常量并且在數(shù)值上與B[0]相同,但類型是int (*)[10]。
網(wǎng)友評論:
定義一個(gè)數(shù)組int A[10],A是一個(gè)常量,類型是int *,一個(gè)常量前加“&”并不是對該常量取地址。&A也是一個(gè)常量,和并且“A”在數(shù)值上是相同的,但"&A"的類型是int (*)[10],所以在42樓的第一種寫**有警告。
...
ShakaLeo 發(fā)表于 2010-2-27 14:55 A確實(shí)是個(gè)常量, 但這個(gè)常量我認(rèn)為在內(nèi)存也是有空間存它的, 就是它也要被放在一個(gè)內(nèi)存地址里, 那么, 為什么&A不是存放A的地址呢? 非要和A相等干嘛? &不是取地址符號么.
比如: A的值為0x0003 地址為0x456366那么, &A應(yīng)該是0x456366啊.
恩, 那&&A又是怎么回事呢? 這個(gè)難道是: A的值沒有加載到data區(qū), 不可能啊, A的值是系統(tǒng)現(xiàn)分配的應(yīng)該................
哪位大俠能詳細(xì)的說下這個(gè)問題
網(wǎng)友評論:[]的優(yōu)先級比*高
討論的挺多,沒細(xì)看,LZ的意思應(yīng)該是糾纏于此吧
網(wǎng)友評論:A確實(shí)是個(gè)常量, 但這個(gè)常量我認(rèn)為在內(nèi)存也是有空間存它的, 就是它也要被放在一個(gè)內(nèi)存地址里, 那么, 為什么&A不是存放A的地址呢? 非要和A相等干嘛? &不是取地址符號么.
比如: A的值為0x0003 地址為0x456366那么, &A ...
sinanjj 發(fā)表于 2010-2-27 23:41
A的值既不在data區(qū),而且和“常變量(即const型變量)”不同,也不在const區(qū),A的值可能在code區(qū),也可能根本沒有一個(gè)固定的位置來存儲A的值。所以&符號不是取地址。下邊是IAR
EWARM環(huán)境下"p=&A"的匯編指令:
LDRR0, [PC, #+808] ;把變量p的地址加載到R0
LDRR1, [PC, #+800] ;把A的值加載到R1
STRR1, [R0, #0] ;把A的值存儲到變量p的地址上
PC+808和PC+800這些位置都是在code區(qū)的。所以“存儲變量p的地址”的位置和“存儲A的值”的位置都是在code區(qū)的。
ARM沒有直接尋址的指令,所以只能把這些值存儲在code區(qū)的某個(gè)位置來間接尋址。對于有直接尋址的MCU來說,甚至沒有存儲A的值的位置,比如AVR,同樣是p=&A, ICCAVR的匯編指令如下:
LDI R24,0x04
LDI R25,0x01 ;數(shù)組A的首地址是0x0104,把A的值加載到R24和R25
STS0x0103,R24
STS0x0102,R25 ;指針p的地址是0x0102,把數(shù)組A的首地址直接存儲到變量p的地址上
可以說A的值是在代碼中,沒有一個(gè)固定的存儲位置,所以這時(shí)候?qū)取地址就更沒有意義了,所以&A不會是對常量A取地址。
對于&&A的寫法,我在上面的兩個(gè)編譯器里都試了一下,都會報(bào)錯(cuò),估計(jì)不是標(biāo)準(zhǔn)用法。
網(wǎng)友評論:A的值既不在data區(qū),而且和“常變量(即const型變量)”不同,也不在const區(qū),A的值可能在code區(qū),也可能根本沒有一個(gè)固定的位置來存儲A的值。所以&符號不是取地址。下邊是IAR EWARM環(huán)境下"p=&A"的匯編指令:
LDR ...
ShakaLeo 發(fā)表于 2010-2-28 08:42
有幸得到骨灰級大俠指點(diǎn), 實(shí)乃萬幸。
那么, 從匯編代碼上看, 也就是說:A指代的地址值在編譯的時(shí)候已經(jīng)確定,并寫入code區(qū),不在程序運(yùn)行中改變了。所以對A取地址無意義。
從這個(gè)解釋上看, 爭論中, HWM前輩實(shí)際對C的理解更勝一籌啊。呵呵。
p=&A; 符合語法解釋但不符合實(shí)際模型。
p=A; 符合實(shí)際模型但語法上說不過去。
再次感謝您的解釋。
網(wǎng)友評論:指針基礎(chǔ)啊
int (*p)[10]指向一個(gè)匿名數(shù)組呀
網(wǎng)友評論:又見申明問題。
p1 = &A; p2 = A; 中 A 是數(shù)組名, 可以被編譯器當(dāng)作常數(shù)對待, 但數(shù)組名就是數(shù)組名, 不是概念的常數(shù). p1 = &A; p2 = A 或許最終在匯編層面都被編譯器作為常數(shù)處理,但在編譯器層面有類型的不同。 &A 不是對常數(shù)取地址,而是對數(shù)組名取地址,即得到一個(gè)指向數(shù)組的指針。 而 p2 = A, p2 只是指向數(shù)組第一個(gè)元素的指針, 不是指向整個(gè)數(shù)組. 這種區(qū)別體現(xiàn)在指針操作上:
p1++; p2++; 此時(shí), p1, p2 指向了不同的地址。
int a1= ((int) (p1+1)) - ((int) p1);
int a2= ((int) (p2+1)) - ((int) p2); 注意 a1, a2 的不同。
另外: 這種申明問題,用我以前講過的一個(gè)中心,兩個(gè)基本點(diǎn)來解題, 就很簡單。 int (*p)[10] 的中心是 *p (因?yàn)槔ㄌ柕膬?yōu)先級), 說明p是一個(gè)指針。 于是整個(gè)申明就是 p 是一個(gè)什么什么的 指針。
網(wǎng)友評論:10#
char *P[10];——>char P[ ][10];// 二維數(shù)組就是個(gè)指針數(shù)組。字符串?dāng)?shù)組中很常用的寫法。
兄弟這個(gè)...char *p[10] ,是不是聲明了一個(gè)10個(gè)元素的指針數(shù)組呢?如果是二維數(shù)組表示的話 是不是char P[10][]呢?
網(wǎng)友評論:呵呵,湊個(gè)熱鬧.
單從C語言的角度的講,涉及到某個(gè)具體的編譯器時(shí),那要看它對C標(biāo)準(zhǔn)支持到什么程度.
有那種比較古老的C編譯器,對指針的處理是寬松的.
如果是符合C99標(biāo)準(zhǔn)的現(xiàn)代編譯器,對指針的處理是"強(qiáng)類型"的,不允許不同類型的指針直接賦值(void* 不在討論范圍).
當(dāng)然你可以強(qiáng)行關(guān)閉"強(qiáng)類型"檢查.
這里我只討論那種"強(qiáng)類型"的C.
這種C語言,強(qiáng)烈區(qū)分"數(shù)組"和"指針",雖然,數(shù)組的名字可以做為它第一個(gè)值的地址來用,
但這仍然是2個(gè)不同的類型.這個(gè)因?yàn)樵贑中使用過于頻繁,特別豁免的("ARM"一書,提起過這個(gè),好像)
int * p1 [10];
int (* p2) [10];
這是2個(gè)不同的類型.
從C語言的運(yùn)算符優(yōu)先級看.
int * p1 [10];
------- p1 是一個(gè)數(shù)組
--------- 數(shù)組的內(nèi)容由指針組成
------------- 指針?biāo)傅膶ο箢愋褪?int
p1是一個(gè)有10個(gè)int *組成的數(shù)組, 即p1的類型是 int *
int (* p2) [10];
------ p2 是一個(gè)指針
----------- 指針?biāo)笇ο笫且粋(gè)10個(gè)對象所組成數(shù)組
--------------- 數(shù)組對象的類型是int
p2 是一個(gè)指向10個(gè)int所組成的對象的指針. 即 p2 的類型是 (int[10])*
int i[10]; // i 是一個(gè)10個(gè)int所組成的數(shù)組
// i 也可以表示 i[0] 的地址, 即 &i[0]
p1 = i; //錯(cuò): p1 是數(shù)組
p1[0] = i;//OK: p1[0]的類型是int*, i是i[0]的地址,也是int*
p2 = i; // 錯(cuò): p2 的類型 (int[10])*, 而i是int[10],即使看作int*,也同p2的類型不同
p2=&i; // OK: p2 的類型 (int[10])*, 而i是int[10], &i(取址),類型當(dāng)然是(int[10])*
網(wǎng)友評論:
定義一個(gè)數(shù)組int A[10],A是一個(gè)常量,類型是int *,一個(gè)常量前加“&”并不是對該常量取地址。&A也是一個(gè)常量,和并且“A”在數(shù)值上是相同的,但"&A"的類型是int (*)[10],所以在42樓的第一種寫**有警告。
...
ShakaLeo 發(fā)表于 2010-2-27 14:55 再饒舌下:
int A[10];
A除了可以表示數(shù)組的首地址外(此時(shí)它的類型是是int *),
同時(shí)它還是個(gè)對象,類型是int[10];
所以是可以對它取址的,即&A是可以的.
同時(shí),因?yàn)锳的地址同A[0]的地址是相同的(因?yàn)樗菙?shù)組嘛),所以下面的程序片段是正確的:
void * p1= A; // p1 = &A[0];
vod * p2 = &A; // p2 = &A;
ASSERT(p1==p2);// 此斷言是成立的
網(wǎng)友評論:再饒舌下:
int A[10];
A除了可以表示數(shù)組的首地址外(此時(shí)它的類型是是int *),
同時(shí)它還是個(gè)對象,類型是int[10];
所以是可以對它取址的,即&A是可以的.
同時(shí),因?yàn)锳的地址同A[0]的地址是相同的(因?yàn)樗菙?shù)組嘛),所以 ...
lenglx 發(fā)表于 2010-3-4 18:47
我并不是說&A這個(gè)表達(dá)式有問題,而是說&號在這里不是對A這個(gè)常量取地址的意思,你可以看看sinanjj在36樓的發(fā)言,再看看我在48樓的分析,A是一個(gè)常量,很有可能只出現(xiàn)在指令的操作數(shù)中,這樣就沒有一個(gè)固定的存儲地址,何來取地址?
網(wǎng)友評論:mark
網(wǎng)友評論:哈!再饒舌一下。A不能叫常量,——A叫做“指針常量。”
指針是一個(gè)地址。所以一個(gè)指針,只能作為“左值”使用。例如:
A=&A[0]; //正確寫法
所以下面寫法有語法問題:
P=A; //地址A 成了右值。
但實(shí)際中為什么可以這么寫?HWM 講過了。編譯器認(rèn)為沒問題。它有它的道理。
P=A;和P=&A;編譯結(jié)果一樣。
把警告級別降低就不會出現(xiàn)警告提示了。
網(wǎng)友評論:P=&A;
所有編譯器都可以無警告通過編譯。
P=A;
少部分編譯器可以通過,但有告警。
大部分編譯器不可以編譯通過。
網(wǎng)友評論:頂 53 樓 lenglx “強(qiáng)類型“。
57樓冷漠概念不清.
數(shù)組就是數(shù)組, 不可以與常量混淆. 某些 compiler(往往無os內(nèi)存管理器) 編譯連接時(shí)靜態(tài)分配內(nèi)存,因而數(shù)組地址在編譯時(shí)可以作為常量嵌入, 連接時(shí)確定, 此時(shí),可以認(rèn)為數(shù)組名 A 是常數(shù)。另外一些compiler, 無法在編譯時(shí)確定地址, 只能在運(yùn)行時(shí)由 os 的內(nèi)存管理器分配后,根據(jù) offset 確定。
"P=A;和P=&A;編譯結(jié)果一樣。", 但概念不一樣。 就如同:
int** p1 = (int**) 1234;
int* p2=(int*) 1234;
int (*p1)[10]; 的定義本身說明了 p1 是一個(gè)“強(qiáng)“類型, 那么還是嚴(yán)格遵照類型去做。
網(wǎng)友評論:1#
我大概看了一下Intp[10], int *p[10], int (*p)[10]
簡單的說:
第一個(gè)定義了10個(gè)整型數(shù)據(jù);
第二個(gè)定義了10個(gè)指針且每個(gè)指針都必須指向INT數(shù)據(jù);
第三個(gè)定義了1個(gè)指針且這個(gè)指針只能指向INTa[10]的數(shù)組
不過在引用時(shí),還有點(diǎn)不會寫。望大俠們修改了。
網(wǎng)友評論:之前一直很糊涂&符號加與不加的區(qū)別,以及多維數(shù)組地址問題,多虧53樓lenglx大俠的講解使我茅塞頓開...
網(wǎng)友評論:我最討厭用指針了
網(wǎng)友評論:int a[10];int*p=a;首先a就是一個(gè)指針,a是一個(gè)指向數(shù)組首個(gè)元素的指針,該元素的類型是整形,那么p也就和a一樣了,p是一個(gè)指向類型為整形數(shù)據(jù)的指針;
int (*p)[10];首先*p就是一個(gè)擁有10個(gè)整形數(shù)據(jù)的數(shù)組(例如:將*p用a代替,a[10]很顯然是數(shù)組),那么p就是一個(gè)指向數(shù)組的指針,組成該數(shù)組的元素是10個(gè)整形數(shù)據(jù)。
不知道這樣了理解對不?歡迎大家拍磚。
網(wǎng)友評論:11樓的這句“ p = A;// 獲得數(shù)組內(nèi)存空間”好像編譯通不過吧?
p是一個(gè)指向類型為數(shù)組的指針,而A是一個(gè)指向類型為整形數(shù)據(jù)的指針,類型的不一樣能賦值過去嗎?
要賦值也起碼需要轉(zhuǎn)換下吧?
typedef int (*ap)[10]
int A[10];
int (*p)[10];
p=(ap)A;
不知道說的對不?歡迎大家拍磚。
網(wǎng)友評論:只知道這么用:
int a;
int *P;
p=&a;
*P==a;
別的什么方法沒有試過,怕出問題,穩(wěn)定最要緊
網(wǎng)友評論:看看《C語言核心編程》和《C和指針》
網(wǎng)友評論:路過
網(wǎng)友評論:《C和指針》
網(wǎng)友評論:學(xué)習(xí)!