int * x [n] [m]和int(* x)[n] [m]之间有什么区别?

时间:2014-04-08 11:02:47

标签: c++ c pointers

我认为int *x[n][m]声明x是指向整数的2-d指针数组,因此分配内存应该像x[i][j] = new int一样简单,并且正如预期的那样工作正常。现在,如果我将声明更改为:

int (*x)[n][m]

x[i][j] = new int不再有效,导致编译错误。

然而,

x = (int(*)[n][m]) malloc (sizeof(int[n][m]))编译。从我运行的几个测试开始,在内存分配之后,不同的声明/分配组合似乎不会影响存储在变量中的值。我错过了什么吗?所以我的问题是, int * x [n] [m]和int(* x)[m] [n]之间是否存在差异。 int(* x)[n] [m]如何存储在内存中?

3 个答案:

答案 0 :(得分:19)

int *a[n][m]是指向int的二维数组指针。

int (*p)[n][m]是指向int的二维数组的指针(它是通过获取int[n][m]的地址获得的类型。)

在这两种情况下,nm都需要编译时间常量,否则声明在C ++中是不合法的(但在C中)。但是,您的编译器可能有一个允许它的扩展名。

第一个可用于模拟三维数组。我说模拟,因为它不是一个具有连续存储的正确数组,并且类型首先是不同的。在a的每个元素中,您可以将地址存储到整数数组的第一个元素中。每个可以具有不同的大小并动态分配。您也可以存储指向单个(可能是堆栈分配的)整数的指针。

int i = 0;
int a1[2] = {};

int* a2[2][2];
a2[0][0] = a1;  // array to pointer decay here
a2[0][1] = new int[42];
a2[1][0] = new int[84];
a2[1][1] = &i;

p可以指向单个2d数组或其数组:

int arr[2][3];
int (*p1)[2][3] = &arr;  // arr decays to int(*)[3], so we need to take the address
int (*p2)[2][3] = new int[42][2][3]; // allocate 42 arrays dynamically

答案 1 :(得分:3)

您可以轻松发现:

  • int * x [n] [m]是指向int的二维指针数组。
  • int(* x)[n] [m]是指向二维数组的指针。

您的问题的答案是第一个是数组,因此内存是“内联” - 它可能是静态的,自动的(在堆栈上)或堆上,具体取决于您定义它的位置。

第二个是指向数组的指针,指针必须在指向它之前初始化。很可能内存将在堆上分配,但也可能是其他地方定义的静态或自动数组。如果在初始化指针之前访问数组的成员,则会出现Undefined Behavior。

答案 2 :(得分:1)

Good site to decode C-declaration names。以您的示例(并替换n=1m=2),我们看到:

int *x[1][2]

转换为:

  

将x声明为指向int

的指针数组2的数组1

尽管

int (*x)[1][2]

转换为:

  

将x声明为指向int

的数组2的数组1的指针