为什么我需要使用二维数组的额外星号?

Why Do I need that extra asterix using 2D array?

我知道如果 arr 是一个数组那么 arr[i]=*(arr+i);如果是二维数组,则 arr[i][j]=*(*(arr+i)+j);所以我有这个代码

main(){
    int arr[5][5];
    int arr2[25];   // same as arr[5][5];
    int i,j;


    for(i=0;i<5;i++)
        for(j=0;j<5;j++){
            arr[i][j]=i+j;
            printf("arr[%d][%d] is at %p\n",i,j,&arr[i][j]);
        }

    printf("*(arr+i)=%d\n",*(arr+1)); // why this dont work


    for(i=0;i<24;i++){
       arr2[i]=i;
       printf("arr2[%d] is at %p\n",i,(arr2+i));
    }

    printf("*(arr+i)=%d\n",*(arr2+1)); // prints 1 as expected
}

我知道在 C 中没有二维数组这样的东西,它基本上是一个线性行主要连续的内存块。所以我想知道为什么我不能使用 *(arr+1) 打印 2D arr 的值,这意味着将 1*5*4 字节添加到 arr 的基址并取消引用该地址处的值。我知道 **(arr+1) 有效,但我不知道为什么我需要那个额外的星号?此外,如果我这样做 printf("*(arr+i)=%p\n",*(arr+1)); 与我将使用 (arr+i) 解释为地址相同

*(arr+1)的类型=arr[1]的类型=int [5],在printf中使用会衰减到int*

要打印指针,请使用:

printf("*(arr+i)=%p\n", *(arr+1));

要打印它指向的对象,请使用:

printf("*(*(arr+i))=%d\n", *(*(arr+1)));

您可以使用以下方法使您的代码更易于阅读:

printf("arr[1] = %p\n", arr[1]);       // Print the pointer
printf("arr[1][0] = %d\n", arr[1][0]); // Print the value

如您所说,C 中的二维数组基本上是一维数组的数组。您可能会将其视为行数组。

最右边的 * 将取消引用外部数组,选择您想要的行。

*(arr+i)      //this gives me a pointer to the row I want

左边的 * 将取消引用内部数组,从行中选择一个元素。

*(*(arr+i)+j) //this gives me an element in the row

**(arr+i) 只是上面的一个特例,其中列号 j0.

arrint 数组的数组。它的类型是int [5][5]。所以,arr 的元素是一维数组。在表达式中使用时,在大多数情况下,数组会转换为指向其第一个元素的指针。在 *(arr + 1) 中,arr 被转换为指向 arr[0] 的指针,即第一个一维数组。添加 1 会将其递增 5*4 = 20 字节,即数组 arr 的下一个元素是 arr[1]

由于arr[1]是一个数组,所以不能打印(整体),但是它的地址可以。 arr[1] 本身是一个数组,它会衰减到指向其第一个元素的指针,即 arr[1][0]。要打印其元素,您需要另一个取消引用,这是通过 arr[1][j] 实现的(j 是列)。

arr[1][j] 等价于 *(arr[1] + j) 最终等价于 *(*(arr + 1) + j)

推荐阅读:What exactly is the array name in c?