2D数组与数组数组

时间:2011-10-31 02:57:18

标签: c++ c multidimensional-array

2D数组和数组数组有什么区别?

我读过评论,例如@Dave's,似乎区分了两者。

  

如果他使用2d数组或指针到数组类型而不是数组数组,则会中断。 - 戴夫

我一直认为两者都提到:

int arr_arr[][];

编辑: @FutureReader,您可能希望看到How do I use arrays in C++?

5 个答案:

答案 0 :(得分:22)

这里有四个不同的概念。

  • 二维数组: int arr[][]。它不能在任何方向上调整大小,并且是连续的。索引它与((int*)arr)[y*w + x]相同。必须静态分配。
  • 指针数组: int (*arr)[]。它只能调整大小以添加更多行,并且是连续的。索引它与((int*)arr)[y*w + x]相同。必须动态分配,但可以释放free(x);
  • 指针指针: int **arr。它可以在任何方向调整大小,并且不一定是方形的。通常动态分配,不一定是连续的,并且释放取决于其构造。索引与*(*(arr+y)+x)相同。
  • 指针数组: int *arr[]。它可以仅调整大小以添加更多列,并且不一定是正方形。调整大小和释放也取决于结构。索引与*(*(arr+y)+x)相同。

其中每一个都可以使用arr[y][x],导致混淆。

答案 1 :(得分:10)

根据定义,二维数组 是一个数组数组。

Dave说的是,在这种情况下,2D数组的定义之间存在不同的语义:

int x[][];

这样:

int *x[];

或者这个:

int **x;

答案 2 :(得分:10)

这里的答案有点微妙。

数组数组定义如下:

int array2[][];

指向数组的指针类型定义为:

int (*array2)[];

指针数组类型定义为:

int* array2[];

编译器对这两者的处理方式略有不同,实际上还有一个选项:

int** array2;

很多人都被告知这三者是相同的,但如果你对编译器了解得更多,你肯定会知道差异很小,但它确实存在。如果你将一个程序替换为另一个程序,很多程序都会运行,但是在编译器和ASM级别,事情并不相同。关于C编译器的教科书应该提供更深入的答案。

此外,如果对2D阵列的实现感兴趣,则有多种方法的效率会有所不同,具体取决于具体情况。您可以将2D数组映射到1D数组,从而确保在处理线性化数据时的空间局部性。如果希望编程简单,并且需要单独操作行/列,则可以使用数组数组。某些被阻止的类型和其他花哨的设计都是缓存智能的,但如果您是用户,则很少需要知道实现。

希望我帮忙!

答案 3 :(得分:1)

以下是可以称为数组数组的2D数组:

int AoA[10][10];

以下是指向已设置为用作2D数组的指针的指针:

int **P2P = malloc(10 * sizeof *P2P);
if(!P2P) exit(1);
for(size_t i = 0; i < 10; i++)
  {
    P2P[i] = malloc(10 * sizeof **P2P);
    if(!P2P[i])
      {
        for(; i > 0; i--)
            free(P2P[i - 1]);
        free(P2P); 
      }
  }

两者都可以通过AoA[x][y]P2P[x][y]访问,但两者不兼容。特别是,P2P = AoA是新手有时期望工作的东西,但不会 - P2P期望指向指针,但当AoA衰变成指针时,它是指针到数组,特别是int (*)[10],这不是int **应该是P2P

答案 4 :(得分:0)

2d数组可以包括:

int x[width * height]; // access: x[x + y * width];

来自维基百科:

  

对于二维数组,具有索引i,j的元素将具有   地址B + c·i + d·j,其中系数c和d是行   和列地址增量。