2D数组和数组的数组有什么区别?我读过一些评论,似乎把两者区分开来:
int** arr = ...; cout << arr[i][j];
如果他使用的是2d数组,或者指向数组的指针类型,而不是数组的数组,则会中断。- @戴夫参见:如何在C++中使用数组?
58wvjzkj1#
这里有四个不同的概念。
*二维数组: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)相同。
int arr[][]
((int*)arr)[y*w + x]
int (*arr)[]
free(x)
int **arr
*(*(arr+y)+x)
int *arr[]
这些都可以使用arr[y][x],导致混淆。
arr[y][x]
yqlxgs2m2#
一个二维数组是一个数组的数组。Dave说的是,在这种情况下,像这样的2D数组的定义之间有不同的语义:
int x[][];
这一点:
int *x[];
或者这个
int **x;
xjreopfe3#
这里的答案有点微妙。数组的数组定义如下:
int array2[][];
数组指针类型定义为:
int (*array2)[];
指针数组类型定义为:
int* array2[];
编译器对这两种情况的处理方式略有不同,实际上还有一个选项:
int** array2;
很多人被教导这三个是相同的,但如果你对编译器了解更多,你肯定会知道差异很小,但它确实存在。如果你用一个程序替换另一个程序,很多程序都会运行,但是在编译器和ASM级别上,情况是不一样的。一本关于C编译器的教科书应该提供一个更深入的答案。此外,如果对2D阵列的实现感兴趣,则有多种方法在效率上有所不同,这取决于情况。您可以将2D数组Map到1D数组,这确保了在处理线性化数据时的空间局部性。如果你想要编程的简单性,或者需要分别操作行/列,你可以使用数组的数组。有某些阻塞类型和其他奇特的设计是缓存智能的,但如果您是用户,则很少需要知道实现。希望我帮到你了!
kupeojn64#
下面是一个二维数组,可以称为数组的数组:
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],这不是P2P应该是的int **。
AoA[x][y]
P2P[x][y]
P2P = AoA
P2P
AoA
int (*)[10]
int **
zengzsys5#
2D数组可以包括:
int x[width * height]; // access: x[x + y * width];
维基百科:对于二维数组,索引为i、j的元素将具有地址B + c · i + d · j,其中系数c和d分别是行和列地址增量。
5条答案
按热度按时间58wvjzkj1#
这里有四个不同的概念。
*二维数组:
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]
,导致混淆。yqlxgs2m2#
一个二维数组是一个数组的数组。
Dave说的是,在这种情况下,像这样的2D数组的定义之间有不同的语义:
这一点:
或者这个
xjreopfe3#
这里的答案有点微妙。
数组的数组定义如下:
数组指针类型定义为:
指针数组类型定义为:
编译器对这两种情况的处理方式略有不同,实际上还有一个选项:
很多人被教导这三个是相同的,但如果你对编译器了解更多,你肯定会知道差异很小,但它确实存在。如果你用一个程序替换另一个程序,很多程序都会运行,但是在编译器和ASM级别上,情况是不一样的。一本关于C编译器的教科书应该提供一个更深入的答案。
此外,如果对2D阵列的实现感兴趣,则有多种方法在效率上有所不同,这取决于情况。您可以将2D数组Map到1D数组,这确保了在处理线性化数据时的空间局部性。如果你想要编程的简单性,或者需要分别操作行/列,你可以使用数组的数组。有某些阻塞类型和其他奇特的设计是缓存智能的,但如果您是用户,则很少需要知道实现。
希望我帮到你了!
kupeojn64#
下面是一个二维数组,可以称为数组的数组:
下面是一个指向一个指针的指针,该指针已被设置为用作2D数组:
两者都可以通过
AoA[x][y]
或P2P[x][y]
访问,但两者不兼容。特别是,P2P = AoA
是新手有时期望工作的东西,但不会-P2P
期望指向指针,但当AoA
衰减为指针时,它是一个指向数组的指针,特别是int (*)[10]
,这不是P2P
应该是的int **
。zengzsys5#
2D数组可以包括:
维基百科:
对于二维数组,索引为i、j的元素将具有地址B + c · i + d · j,其中系数c和d分别是行和列地址增量。