[英]Pointer to a pointer in C not working as expected
我正在學習C語言中的指針。我有一個2D整數數組,並且試圖將所有元素添加到一行中。 2D陣列名稱是a
。 我知道a
是指向數組行的指針,數組本身就是整數元素的指針。 我想遍歷整個數組a
。 因此,我聲明了一個指針**pp
等於a
,因為a
是指向指針的指針。 但是程序在運行時崩潰。
int main(void){
int sum=0;
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int **pp = NULL;
int *p = NULL;
for (pp=a;pp<a+3;pp++){
for (p=*pp;p<*pp+3;p++)
sum += *p;
printf("sum = %d\n", sum);
sum = 0;
}
}
我知道2D數組的第一個對象的地址只是a
。 第二個對象的地址是a+1
,依此類推。 矩陣元素i,j
例如將是*(*(a+i)+j)
。 換句話說,如果我將指針變量pp
設置為(a+i)
,我知道我位於第i行。 第i行的第一個整數元素的地址是*(a+i)
,這就是為什么我使p=*pp
。 因此元素(i,0)
應該是*p
,與*(*(a+i)+0)
。 那么,為什么代碼沒有按預期運行呢?
2D數組不是指向指針的指針。 通常,數組不是指針,指針也不是數組。 永遠記住
“指針算術和數組索引在C中是等效的,指針和數組是不同的”。
a
是3
int
的3
數組的數組。 pp
是指向int
指針。 在表達式中使用時,大多數情況下,數組會轉換為指向其第一個元素的指針 。 因此,在pp = a;
,將a
轉換為與pp
的類型int **
不兼容的int (*)[3]
。 將pp
聲明為int (*)[3]
。
int (*pp)[3];
以下代碼也可以正常運行,盡管需要強制轉換:
int main(void){
int sum = 0;
int a[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int *pp = (int*)a;
for (int i = 0; i < 3; ++i){
for (int j = 0; j < 3; ++j){
sum += *pp;
pp++;
}
printf("sum = %d\n", sum);
sum = 0;
}
}
這是一個學術例子,因為您根本不需要指針。 關鍵是a基本上是數組開始的內存地址。 因此,我可以將第一個元素轉換為指向int的指針。 通過執行pp ++可以達到以下所有整數; 它只是將指針與sizeof(int)向右移動。 這樣,您基本上可以以線性方式遍歷多維數組。
我同意Philip Stuyck的解決方案。 我只是想闡明為什么您會出現段錯誤(我建議使用GDB或其他調試器來幫助您弄清指針的狀態)。
所以這是您的數組,一個:
(gdb) p &a
$14 = (int (*)[3][3]) 0x7fffffffdb10
(gdb) x/9wd a
0x7fffffffdb10: 1 2 3 4
0x7fffffffdb20: 5 6 7 8
0x7fffffffdb30: 9
您的指針pp指向一個:
(gdb) p pp
$15 = (int **) 0x7fffffffdb10
當取消引用pp(即int **)時,您將獲得int *。 在64位計算機上,這是8個字節,因此是垃圾地址:
(gdb) p *pp
$16 = (int *) 0x200000001
(gdb) p (int) *pp
$17 = 1
因此,當您設置p = * pp,然后嘗試取消引用它時,您會發現以下錯誤:
(gdb) p p
$18 = (int *) 0x200000001
(gdb) p *p
Cannot access memory at address 0x200000001
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.