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