为什么我需要使用2D数组的额外asterix?

时间:2015-03-12 19:18:11

标签: c arrays pointers memory-management

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

3 个答案:

答案 0 :(得分:3)

arrint s的数组数组。它的类型是int [5][5]。因此,arr的元素是一维数组。在表达式中使用时,在大多数情况下,数组转换为指向其第一个元素的指针。在*(arr + 1)中,arr被转换为指向arr[0]的指针,即第一个1D数组。添加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?

答案 1 :(得分:2)

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

要打印指针,请使用:

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

答案 2 :(得分:2)

正如你所说,C中的2D数组基本上是一维数组的数组。您可能会将此视为行数组。

最右边的*将取消引用外部数组,选择所需的行。

*(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