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
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)
{
/* ... */
int** memory = malloc(sizeof(*memory)*400);
for (int i=0 ; i < 400 ; i++)
{
memory[i] = malloc(sizeof(int)*200);
}
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.
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;
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;
}
#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 );
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:
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];
And a pointer:
static int* pointer;
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:
array
de-reference:
i
,array
, i.e. its fixed address, to form target memory address,pointer
de-reference:
i
,pointer
, i.e. the contents at its 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.
@caf here has the right solution. There's a legal way within the language to index a pointer as two-dimentional array after all.