这两个指针声明有什么区别

时间:2016-04-20 16:54:00

标签: c arrays pointers

这里我有一个2D数组。我想声明一个指向数组第一行的指针。首先,我做了类似的事情

#include <stdio.h>

int main ()
{
   int arr[2][2]={{6,2},{3,4}};
   int *ptr=arr;

   printf("%d",*(ptr+0));
}

2D阵列的第一行也是一个数组。一维数组的类似类型的指针声明不会发出任何警告。为什么我在编译期间收到警告。

  

[警告]从不兼容的指针类型初始化[启用   默认]

以下没有发出任何警告

int main ()
{
   int arr[2][2]={{6,2},{3,4}};
   int (*ptr)[2]=arr;

   printf("%d",*(ptr+0));
}

3 个答案:

答案 0 :(得分:2)

除非它是sizeof或一元&运算符的操作数,否则表达式类型为“N - 元素数组{{1} “将被转换(”衰减“)到”指向T的指针“类型的表达式,表达式的值将是数组的第一个元素的地址。

在第

T
表达式 int *ptr=arr; 的类型为“{element}的2元素数组的2元素数组”(IOW,arr是“2元素数组” int“)。由于表达式T不是int或一元arr运算符的操作数,因此它被转换(“衰减”)到类型为“指向2元素数组的指针”的表达式sizeof“或&,表达式的值是数组第一个元素的地址。

这就是为什么你得到了上面一行的警告,而不是

int

因为在这种情况下类型匹配正确。

鉴于声明

int (*)[2]

以下都是真的:

int (*ptr)[2]=arr;

所以int arr[2][2]={{6,2},{3,4}}; Expression Type Decays To Equivalent Value ---------- ---- --------- ---------------- arr int [2][2] int (*)[2] &arr[0][0] &arr int (*)[2][2] &arr[0][0] *arr int [2] int * &arr[0][0] arr[i] int [2] int * &arr[i][0] &arr[i] int (*)[2] &arr[i][0] *arr[i] int arr[i][0] arr[i][j] int &arr[i][j] int * arr&arrarr[0]都评估为相同的(地址)数组的第一个元素与数组本身的地址相同,但类型都是不同的。

我想要了解的一个非常重要的一点(特别是因为它出现在其他几个答案中)是数组对象存储任何指针值。如果您查看内存中&arr[0]的内容,您会看到以下内容:

&arr[0][0]

任何指针都没有存储空间。编译代码时,任何引用数组的表达式都会被替换,并带有指向数组第一个元素的指针。

答案 1 :(得分:1)

arr是整数数组的数组,而ptr是指向整数的指针。在数组数组中,您需要两个间接级别来达到整数(arr[0][0]),而在指针中只需要一个(ptr[0])。您可以将某个类型的元素数组分配给指向同一类型元素的指针,但如果类型不同则不会,这是这种情况。

正如您所看到的,它们是两个不同的东西,因此编译器可以很好地对您的分配抱怨。

答案 2 :(得分:-2)

2D数组包含(如arrurri所提到的)一个指向指针数组的指针,每个指针都指向实际的元素。所以,arr是一个指向指针的指针,它的每个索引值(arr [i])是一个指向行的指针。

那么,你需要做的是ptr = arr [0];代替。