malloc in C, but use multi-dimensional array syntax

后端 未结 8 994
失恋的感觉
失恋的感觉 2020-12-04 22:59

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 MAGICV         


        
相关标签:
8条回答
  • 2020-12-04 23:12

    Yes, you can do this, and no, you don't need another array of pointers like most of the other answers are telling you. The invocation you want is just:

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

    If you wish to declare a function returning such a pointer, you can either do it like this:

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

    Or use a typedef, which makes it a bit clearer:

    typedef int (*arrayptr)[200];
    
    arrayptr function(void)
    {
        /* ... */
    
    0 讨论(0)
  • 2020-12-04 23:19
    int** memory = malloc(sizeof(*memory)*400); 
    for (int i=0 ; i < 400 ; i++) 
    {
        memory[i] = malloc(sizeof(int)*200);
    }
    
    0 讨论(0)
  • 2020-12-04 23:21

    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.

    0 讨论(0)
  • 2020-12-04 23:29

    If extra indirection isn't a concern, you can use an array of pointers.

    Edit

    Here's a variation on @Platinum Azure's answer that doesn't make so many calls to malloc. Besides faster allocation, all the elements are guaranteed to be contiguous:

    #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;
    
    0 讨论(0)
  • 2020-12-04 23:34

    Use a pointer to arrays:

    #include <stdio.h>
    #include <stdlib.h>
    
    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;
    }
    
    0 讨论(0)
  • 2020-12-04 23:34
    #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 );
    

    Edit:

    Arrays and pointers look very much the same, but the compiler treats them very differently. Let's see what needs to be done for an array indexing and de-referencing a pointer with offset:

    1. Say we declared a static array (array on the stack is just a bit more complicated, fixed offset from a register, but essentially the same):

      static int array[10];

    2. And a pointer:

      static int* pointer;

    3. We then de-deference each as follows:

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

    The thing to note is that address of the beginning of array, as well as, address of pointer (not its contents) are fixed at link/load time. Compiler then does the following:

    1. For array de-reference:
      • loads value of i,
      • adds it to the value of array, i.e. its fixed address, to form target memory address,
      • loads the value from calculated address
    2. For pointer de-reference:
      • loads the value of i,
      • loads the value of pointer, i.e. the contents at its address,
      • adds two values to form the effective address
      • loads the value from calculated address.

    Same happens for 2D array with additional steps of loading the second index and multiplying it by the row size (which is a constant). All this is decided at compile time, and there's no way of substituting one for the other at run-time.

    Edit:

    @caf here has the right solution. There's a legal way within the language to index a pointer as two-dimentional array after all.

    0 讨论(0)
提交回复
热议问题