malloc in C, but use multi-dimensional array synta

2019-01-13 11:17发布

Is there any way to malloc a large array, but refer to it with 2D syntax? I want something like:

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


UPDATE: This was important to mention: I just want to have one contiguous block of memory. I just don't want to write a macro like:

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

and then refer to my blob like:

memory[INDX(a,b)];

I'd much prefer:

memory[a][b];


UPDATE: I understand the compiler has no way of knowing as-is. I'd be willing to supply extra information, something like:

int *MAGICVAR[][200] = memory;

Does no syntax like this exist? Note the reason I don't just use a fixed width array is that it is too big to place on the stack.


UPDATE: OK guys, I can do this:

void toldyou(char MAGICVAR[][286][5]) {
  //use MAGICVAR
}

//from another function:
  char *memory = (char *)malloc(sizeof(char)*1820*286*5);
  fool(memory);

I get a warning, passing arg 1 of toldyou from incompatible pointer type, but the code works, and I've verified that the same locations are accessed. Is there any way to do this without using another function?

8条回答
爷、活的狠高调
2楼-- · 2019-01-13 12:15

Working from Tim's and caf's answers, I'll leave this here for posterity:

#include <stdio.h>
#include <stdlib.h>

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;
}
查看更多
可以哭但决不认输i
3楼-- · 2019-01-13 12:17

In the same vein as Cogwheel's answer, here's a (somewhat dirty) trick that makes only one call to 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);

This fills the first part of the buffer with pointers to each row in the immediately following, contiguous array data.

查看更多
登录 后发表回答