Chr*_*per 165 c memory arrays stack-memory data-structures
在C中,我知道我可以使用以下代码在堆上动态分配二维数组:
int** someNumbers = malloc(arrayRows*sizeof(int*));
for (i = 0; i < arrayRows; i++) {
someNumbers[i] = malloc(arrayColumns*sizeof(int));
}
Run Code Online (Sandbox Code Playgroud)
显然,这实际上会创建一个指向一堆独立的一维整数数组的指针的一维数组,而"系统"可以在我要求时找出我的意思:
someNumbers[4][2];
Run Code Online (Sandbox Code Playgroud)
但是,当我静态声明一个2D数组时,如下一行...:
int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];
Run Code Online (Sandbox Code Playgroud)
...是否在堆栈上创建了类似的结构,还是完全是另一种形式?(即它是指针的一维数组吗?如果没有,它是什么,以及如何计算它的引用?)
另外,当我说"系统"时,究竟是什么负责解决这个问题呢?内核?或者C编译器在编译时对其进行排序?
Car*_*rum 129
静态二维数组看起来像一个数组数组 - 它只是在内存中连续布局.数组与指针不同,但因为你可以经常互换地使用它们,有时会让人感到困惑.然而,编译器会正确地跟踪,这使得一切都很好地排列.你必须要小心你所提到的静态二维数组,因为如果你试图将一个数组传递给一个带int **
参数的函数,那么坏事就会发生.这是一个简单的例子:
int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};
Run Code Online (Sandbox Code Playgroud)
在内存中看起来像这样:
0 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)
完全相同:
int array2[6] = { 0, 1, 2, 3, 4, 5 };
Run Code Online (Sandbox Code Playgroud)
但是如果你试图传递array1
给这个函数:
void function1(int **a);
Run Code Online (Sandbox Code Playgroud)
你会得到一个警告(并且应用程序无法正确访问数组):
warning: passing argument 1 of ‘function1’ from incompatible pointer type
Run Code Online (Sandbox Code Playgroud)
因为2D数组不一样int **
.将数组自动衰减为指针只会"深入一层",可以这么说.您需要将函数声明为:
void function2(int a[][2]);
Run Code Online (Sandbox Code Playgroud)
要么
void function2(int a[3][2]);
Run Code Online (Sandbox Code Playgroud)
让一切快乐.
同样的概念扩展到n维数组.但是,在您的应用程序中利用这种有趣的业务通常只会让人更难理解.所以要小心.
caf*_*caf 79
答案是基于C不具备 2D数组的想法- 它具有数组数组.当你声明这个时:
int someNumbers[4][2];
Run Code Online (Sandbox Code Playgroud)
您要求someNumbers
是一个包含4个元素的数组,其中该数组的每个元素都是类型int [2]
(它本身就是一个2 int
的数组).
这个难题的另一部分是数组总是在内存中连续排列.如果你要求:
sometype_t array[4];
Run Code Online (Sandbox Code Playgroud)
那总是这样:
| sometype_t | sometype_t | sometype_t | sometype_t |
Run Code Online (Sandbox Code Playgroud)
(4个sometype_t
物体彼此相邻放置,中间没有空格).所以在你的someNumbers
数组数组中,它看起来像这样:
| int [2] | int [2] | int [2] | int [2] |
Run Code Online (Sandbox Code Playgroud)
每个int [2]
元素本身就是一个数组,如下所示:
| int | int |
Run Code Online (Sandbox Code Playgroud)
总的来说,你得到这个:
| int | int | int | int | int | int | int | int |
Run Code Online (Sandbox Code Playgroud)
小智 26
unsigned char MultiArray[5][2]={{0,1},{2,3},{4,5},{6,7},{8,9}};
Run Code Online (Sandbox Code Playgroud)
在内存中等于:
unsigned char SingleArray[10]={0,1,2,3,4,5,6,7,8,9};
Run Code Online (Sandbox Code Playgroud)
在回答你的同时:两者,虽然编译器正在做大部分繁重的工作.
在静态分配的数组的情况下,"系统"将是编译器.它将像任何堆栈变量一样保留内存.
对于malloc'd数组,"The System"将是malloc的实现者(通常是内核).所有编译器将分配的是基指针.
编译器总是将处理类型作为它们声明的类型,除了在Carl给出的示例中它可以找出可互换的用法.这就是为什么如果你将一个[] []传递给一个函数,它必须假定它是一个静态分配的平面,其中**被假定为指向指针的指针.