在C中的malloc,但使用多维数组语法

有没有什么方法可以malloc一个大型数组,但用2D语法引用它? 我想要的东西:

int *memory = (int *)malloc(sizeof(int)*400*200); int MAGICVAR = ...; MAGICVAR[20][10] = 3; //sets the (200*20 + 10)th element 

更新:这一点很重要:我只想拥有一个连续的内存块。 我只是不想写一个像:

 #define INDX(a,b) (a*200+b); 

然后参考我的blob:

 memory[INDX(a,b)]; 

我更喜欢:

 memory[a][b]; 

更新:我理解编译器无法按原样知道。 我愿意提供额外的信息,例如:

 int *MAGICVAR[][200] = memory; 

没有这样的语法吗? 请注意我不仅使用固定宽度数组的原因是它太大而无法放在堆栈上。


更新:伙计们,我可以这样做:

 void toldyou(char MAGICVAR[][286][5]) { //use MAGICVAR } //from another function: char *memory = (char *)malloc(sizeof(char)*1820*286*5); fool(memory); 

我收到一个警告, passing arg 1 of toldyou from incompatible pointer type ,但代码工作,我已经validation了访问相同的位置。 没有使用其他function有没有办法做到这一点?

是的,你可以这样做,不,你不需要像大多数其他答案告诉你的另一个指针数组。 你想要的调用只是:

 int (*MAGICVAR)[200] = malloc(400 * sizeof *MAGICVAR); MAGICVAR[20][10] = 3; // sets the (200*20 + 10)th element 

如果你想声明一个返回这样一个指针的函数,你可以这样做:

 int (*func(void))[200] { int (*MAGICVAR)[200] = malloc(400 * sizeof *MAGICVAR); MAGICVAR[20][10] = 3; return MAGICVAR; } 

或者使用typedef,这使它更清晰:

 typedef int (*arrayptr)[200]; arrayptr function(void) { /* ... */ 

使用指向数组的指针:

 #include  #include  int main() { int (*arr)[10]; arr = malloc(10*10*sizeof(int)); for (int i = 0; i < 10; i++) for(int j = 0; j < 10; j++) arr[i][j] = i*j; for (int i = 0; i < 10; i++) for(int j = 0; j < 10; j++) printf("%d\n", arr[i][j]); free(arr); return 0; } 

如果不关心额外的间接,则可以使用指针数组。

编辑

这是@Platinum Azure的答案的变体,它没有对malloc进行如此多的调用。 除了更快的分配,所有元素都保证是连续的:

 #define ROWS 400 #define COLS 200 int **memory = malloc(ROWS * sizeof(*memory)); int *arr = malloc(ROWS * COLS * sizeof(int)); int i; for (i = 0; i < ROWS; ++i) { memory[i] = &arr[i * COLS]; } memory[20][10] = 3; 

与Cogwheel的回答一样,这里有一个(有点脏)技巧,只能调用malloc()

 #define ROWS 400 #define COLS 200 int** array = malloc(ROWS * sizeof(int*) + ROWS * COLS * sizeof(int)); int i; for (i = 0; i < ROWS; ++i) array[i] = (int*)(array + ROWS) + (i * COLS); 

这将填充缓冲区的第一部分,并指向紧随其后的连续数组数据中的每一行。

 #define ROWS 400 #define index_array_2d(a,i,j) (a)[(i)*ROWS + (j)] ... index_array_2d( memory, 20, 10 ) = -1; int x = index_array_2d( memory, 20, 10 ); 

编辑:

数组和指针看起来非常相似,但编译器对它们的处理方式却截然不同。 让我们看一下数组索引和取消引用带偏移量的指针需要做什么:

  1. 假设我们声明了一个静态数组(堆栈上的数组只是更复杂,从寄存器固定偏移,但基本相同):

    static int array[10];

  2. 一个指针:

    static int* pointer;

  3. 然后我们按照以下方式对每个进行去除:

    x = array[i];
    x = pointer[i];

需要注意的是, array开头的地址以及pointer地址(不是其内容)在链接/加载时固定 。 编译器然后执行以下操作:

  1. 对于array取消引用:
    • 加载i值,
    • 将它添加到array的值,即其固定地址,以形成目标内存地址,
    • 从计算的地址加载值
  2. 对于pointer取消引用:
    • 加载i的值,
    • 加载pointer的值,即其地址的内容
    • 添加两个值以形成有效地址
    • 从计算的地址加载值。

对于2D数组也是如此,其中包括加载第二个索引并将其乘以行大小(这是一个常量)的附加步骤。 所有这些都是在编译时决定的,并且在运行时无法用一个代替另一个。

编辑:

@caf这里有正确的解决方案。 在语言中有一种合法的方法可以将指针索引为二维数组。

编译器和运行时无法通过malloc调用中的乘法来了解您的预期维度容量。

您需要使用双指针才能实现两个索引的function。 这样的事情应该这样做:

 #define ROWS 400 #define COLS 200 int **memory = malloc(ROWS * sizeof(*memory)); int i; for (i = 0; i < ROWS; ++i) { memory[i] = malloc(COLS * sizeof(*memory[i]); } memory[20][10] = 3; 

确保检查所有malloc返回值以返回NULL,指示内存分配失败。

根据蒂姆和咖啡馆的答案,我将把这个留给后人:

 #include  #include  void Test0() { int c, i, j, n, r; int (*m)[ 3 ]; r = 2; c = 3; m = malloc( r * c * sizeof(int) ); for ( i = n = 0; i < r; ++i ) { for ( j = 0; j < c; ++j ) { m[ i ][ j ] = n++; printf( "m[ %d ][ %d ] == %d\n", i, j, m[ i ][ j ] ); } } free( m ); } void Test1( int r, int c ) { int i, j, n; int (*m)[ c ]; m = malloc( r * c * sizeof(int) ); for ( i = n = 0; i < r; ++i ) { for ( j = 0; j < c; ++j ) { m[ i ][ j ] = n++; printf( "m[ %d ][ %d ] == %d\n", i, j, m[ i ][ j ] ); } } free( m ); } void Test2( int r, int c ) { int i, j, n; typedef struct _M { int rows; int cols; int (*matrix)[ 0 ]; } M; M * m; m = malloc( sizeof(M) + r * c * sizeof(int) ); m->rows = r; m->cols = c; int (*mp)[ m->cols ] = (int (*)[ m->cols ]) &m->matrix; for ( i = n = 0; i < r; ++i ) { for ( j = 0; j < c; ++j ) { mp[ i ][ j ] = n++; printf( "m->matrix[ %d ][ %d ] == %d\n", i, j, mp[ i ][ j ] ); } } free( m ); } int main( int argc, const char * argv[] ) { int cols, rows; rows = 2; cols = 3; Test0(); Test1( rows, cols ); Test2( rows, cols ); return 0; } 
 int** memory = malloc(sizeof(*memory)*400); for (int i=0 ; i < 400 ; i++) { memory[i] = malloc(sizeof(int)*200); }