[英]C assigning the address of a 2D array to a pointer
我正在閱讀一些講義,為了使指針引用2D數組,必須給出第一個元素的地址。
int a[10][10];
int *p = &a[0][0];
我從來沒有嘗試過這個,所以我很好奇為什么不足以將數組本身分配給指針,就像在1D情況下那樣。
int a[10][10];
int *p = a;
無論如何,數組都保存在不間斷的“內存”行中,而2D數組只有不同的類型,但結構與1D數組相同。
通過做這個
int *p = &a[0][0];
我沒有看到我們如何給指針提供更多信息而不是這樣做
int *p = a;
或者也許所有數組都不管它們的維數是否相同,唯一的區別是多維數組在第一個元素之前存儲它們的額外維度,我們需要跳過那些記住數組維度大小的內存空間?
首先,一些背景:
除了當它是的操作數sizeof
或一元&
運營商,或者是一個字符串被用來初始化一個聲明另一個數組,類型“的N元件陣列的表達 T
將被轉換(“衰變”)”,以表達式“指向T
指針”,表達式的值將是數組的第一個元素的地址。
鑒於聲明
int a[10][10];
表達 a
具有類型“的10個元素的數組的10個元素的數組int
”。 除非此表達式是sizeof
或一元&
運算符的操作數,否則它將轉換為“指向10元素數組的int
”或int (*)[10]
類型的表達式。
鑒於該聲明,以下所有情況均屬實:
Expression Type Decays to
---------- ---- ---------
a int [10][10] int (*)[10]
&a int (*)[10][10]
*a int [10] int *
a[i] int [10] int *
&a[i] int (*)[10]
*a[i] int
a[i][j] int
&a[i][j] int *
也,
sizeof a == sizeof (int) * 10 * 10
sizeof &a == sizeof (int (*)[10][10])
sizeof *a == sizeof (int) * 10
sizeof a[i] == sizeof (int) * 10
sizeof &a[i] == sizeof (int (*)[10] )
sizeof *a[i] == sizeif (int)
sizeof a[i][j] == sizeof (int)
sizeof &a[i][j] == sizeof (int *)
請注意,不同的指針類型int (*)[10][10]
, int (*)[10]
和int *
不必具有相同的大小或具有相同的表示,盡管在平台上我是熟悉他們。
數組的第一個元素的地址與數組本身的地址相同; 因此,所有a
, &a
, a[0]
, &a[0]
和&a[0][0]
將產生相同的值 ,但類型將不同(如上表所示)。
因此,假設我們添加以下聲明:
int *p0 = &a[0][0]; // equivalent to int *p0 = a[0];
int (*p1)[10] = &a[0]; // equivalent to int (*p1)[10] = a;
int (*p2)[10][10] = &a;
所有p0
, p1
和p2
最初都具有相同的值,這是a
第一個元素的地址; 但是,由於指針類型不同,涉及指針運算的結果操作會有所不同。 表達式p0 + 1
將產生下一個int
對象的地址( &a[0][1]
)。 表達式p1 + 1
將產生下一個10元素 int
( &a[1][0]
)的地址。 最后,表達式p2 + 1
將產生10個元素int
的下一個10元素數組的地址(實際上, &a[11][0]
)。
注意p1
和p2
的類型; 既不是簡單的int *
,因為用於初始化它們的表達式不是那種類型(參見第一個表)。
注意模式; 對於數組類型,表達式越簡單,相應類型就越復雜。 表達式a
不引用單個int
對象; 它指的是10x10的int
對象數組,因此當它出現在表達式中時,它被視為指向整數數組的指針,而不是指向單個整數的指針。
編譯器知道“a”是指向十個整數的指針。 如果未聲明維度,則編譯器會將新指針視為指向未知數量的整數的指針。 這將適用於您的情況,但它會生成編譯器警告,因為編譯器將它們視為不兼容的指針。 您嘗試執行的操作的語法(不生成編譯器警告)是:
int a[10][10];
int *p1 = &a[0][0];
int (*p2)[10] = a;
printf("p1: %p p2: %p\n", p1, p2);
這很重要的一個原因是指針算術:
p1++; //move forward sizeof(int) bytes
p2++; //move forward sizeof(int) * 10 bytes
你的理解很接近,不同的是類型信息。 指針確實有它的類型。 例如int * p,指針類型是int *,如int a [10] [10],相應的指針類型是int * [10] [10]。
在您的示例中,p和a do指向相同的地址,但它們是不同的類型,這對它們執行算術運算很重要。
以下是此網址的示例
假設我們現在定義了三個指針:
char *mychar;
short *myshort;
long *mylong;
並且我們知道它們分別指向存儲器位置1000,2000和3000。
因此,如果我們寫:
++mychar;
++myshort;
++mylong;
正如人們所預料的那樣,mychar將包含值1001.但不是那么明顯,myshort將包含值2002,而mylong將包含3004,即使它們每個只增加一次。 原因是,當向指針添加一個指針時,指針指向相同類型的后續元素,因此,指向它的類型的字節大小將添加到指針。
你是對的,你可以將數組本身分配給指針:
int a[10][10] = {[0][0]=6,[0][1]=1,[1][0]=10,[1][1]=11};
int b[10][10][10] = {[0][0][0]=8,[0][0][1]=1,[0][1][0]=10,[1][0][0]=100};
int *p, *q, *r, *s;
p = &a[0][0];
q = a; // what you are saying
r = &b[0][0][0];
s = b; // what you are saying
printf("p= %p,*p= %d\n",p,*p);
printf("q= %p,*q= %d\n",q,*q);
printf("r= %p,*r= %d\n",r,*r);
printf("s= %p,*s= %d\n",s,*s);
輸出是:
p= 0xbfdd2eb0,*p= 6
q= 0xbfdd2eb0,*q= 6
r= 0xbfdd3040,*r= 8
s= 0xbfdd3040,*s= 8
無論矩陣的大小如何,它們都指向相同的地址。 所以,你說的是對的。
在2D數組中, *a
和a
的結果是相同的,它們都指向這個2D數組的第一個地址!
但是如果你想定義一個指向這個數組的指針,你可以使用int (*ptr)[10]
。
你是對的,1D和2D共享相同的結構,但2D對上面的指針有一些額外的操作。
總而言之,在2D數組中, a
, *a
和&a[0][0]
打印相同的地址,但它們的用法可能會有所不同。
像這樣:
#include<stdio.h>
int main() {
int a[10][10];
int *pa1 = &a[0][0];
int *pa2 = *a;
printf("pa1 is %p\n", pa1);
printf("pa2 is %p\n", pa2);
printf("Address of a is %p\n", a);
// pointer to array
int (*pa3)[10];
pa3 = a;
printf("pa3 is %p\n", pa3);
return 0;
}
他們打印相同的地址。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.