簡體   English   中英

指向C中的指針的指針未按預期工作

[英]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中是等效的,指針和數組是不同的”。

a3 int3數組的數組。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM