我知道如果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)
解释为地址相同
答案 0 :(得分:3)
arr
是int
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)
。
答案 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)
只是上述特殊情况,其中列号j
为0
。