How to create at runtime a two dimensional array in C - c

I cannot create a 2D array from 2 variables (eg int arr[i][j] not allowed) so how would I create a dynamically sized 2D array?
The dimensions of the array are only known at runtime in my program. The array is to represent a grid. How would I code this in C?

First allocate an array of pointers.
/* size_x is the width of the array */
int **array = (int**)calloc(size_x, sizeof(int*));
Then allocate each column.
for(int i = 0; i < size_x; i++)
{
/* size_y is the height */
array[i] = (int*)calloc(size_y, sizeof(int));
}
You can access the elements with array[i][j]. Freeing the memory is done in 'reverse' order:
for(int i = 0; i < size_x; i++)
{
free(array[i]);
}
free(array);

You have to allocate a 1-dimensional array:
int* array = calloc(m*n, sizof(int));
And access it like this:
array[i*n + j]
The compiler does exactly this when accessing two-dimensional arrays, and will probably output the same code when n can be guessed at compile time.

This is a FAQ on comp.lang.c (I took the liberty to add the c-faq tag), it even has a FGA (frequently given answer :-)
See http://c-faq.com/aryptr/index.html, 6.16 How can I dynamically allocate a multidimensional array?

In C a multidimensional array is just an array for which each element is another array.
So you need to first allocate memory for one array (the rows). You can use the malloc() function which will return a pointer to the array.
Then you iterate through the array and for each element you allocate memory for the number of columns.
NOTE: don't forget to free the memory you manually allocate with the free() function in the same way you used malloc() to allocate it.

Some of the examples show multiple (more than 2) allocations for the array; it is perfectly feasible to do it in just two allocations (error checking omitted) for an n × m array:
int **array = calloc(m, sizeof(*array));
int *data = calloc(m * n, sizof(*data));
for (int i = 0; i < m; i++)
array[i] = &data[i * n];
...use array[i][j]...
free(array[0]);
free(array);

Related

Dynamic memory allocation of 2d array

In this code, while we are dynamically allocating memory for the 2D array, after 4 address why it is taking a gap of 16 bytes but when we are statically allocating 2D array then it does not have such gap.... what is the reason behind this???
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r = 3, c = 4, i, j, count;
int stat[r][c];
int *arr[r];
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(arr+i)+j);
printf("\n\n");
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(stat+i)+j);
/* Code for further processing and free the
dynamically allocated memory */
return 0;
}
Because you are not allocating a 2D array. You are allocating a set of 1D arrays, and those allocations do not have to be contiguous (most malloc implementations reserve some bytes to store the size of the allocated block).
To dynamically allocate a "true" 2D array where number of rows and columns aren't known until runtime, you'd do something like this:
stat (*arr)[c] = malloc( sizeof *arr * r );
that would be contiguous like any "normal" 2D array.
But...
Strictly speaking, this behavior is undefined - since arr points to a VLA, the sizeof *arr expression must be evaluated at runtime, not at compile time, and arr is not a valid pointer value at that point. I've never seen this fail on any implementation I've used, but that doesn't mean it won't fail somewhere. If c were constant instead, like
stat (*arr)[3] = malloc( sizeof *arr * r );
then there wouldn't be a problem, and this would be the preferred way to dynamically allocate an Nx3 array.
If you need all array elements to be contiguous (such that you could traverse the entire array with a pointer or something like that), then the safest option is to allocate your memory as a 1D array:
stat *arr = malloc( sizeof *arr * r * c );
and compute the offsets manually:
x = arr[ i * r + j ];
If you want the convenience of 2D notation, you could try creating a pointer and setting to point to the beginning of the array, something like
stat (*ptr)[c] = (stat (*)[c]) arr;
but that kind of pointer aliasing is also undefined if the pointer types are not compatible, and we've no reason to expect that a pointer to T is compatible with a pointer to an array of T.
The comments on your question have the most essential advice - don't worry about where malloc puts your memory. There is no assurance that it will be in any order. It may locate allocations in pursuit of various optimizations or speculations, and may vary from one execution to the next. If nothing else, other memory allocations, calls to free, garbage collection (in languages with GC, that is) between your calls to malloc will affect the location of the next allocation.
This can also vary with compiler, compiler options, OS, etc.
As for the specific reason your allocations have a 16 byte gap, that's impossible to say without more, and likely very deep, insight into your scenario. BTW, you didn't include output of your printf in your question.
But if I had to guess, I'd say the memory manager was aligning the allocations up with memory boundaries...perhaps a 32-byte or 64-byte boundary.
You're allocating 4 * sizeof(int). If an int is 4 bytes on your system, that's 16 bytes. If your malloc likes to line things up to 32 bytes, that might explain the 16-byte gaps you're seeing.
But again...this is just a guess. The simple answer is...you shouldn't care.
But if you DO care for some reason, you probably need to do your own allocation. malloc a much larger chunk of memory, and then manage your own pointers and allocations internally.

Shift elements by one index with memmove

I am trying to shift the elements in a dynamically created 3d array by one index, so that each element [i][j][k] should be on [i+1][j][k].
This is how my array creation looks like
typedef struct stencil{
int ***arr;
int l;
int m;
int n;}matrix;
void createMatrix(matrix *vector){
vector->arr = (int***) malloc(sizeof(int**) * (vector->l+2));
for (int i = 0; i< vector->l+2; ++i) {
vector->arr[i] = (int**) malloc(sizeof(int*) * (vector->m+2));
for (int j = 0; j < vector->m+2; ++j) {
vector->arr[i][j] = (int*) calloc((vector->n+2),sizeof(int));
}
}
}
This is basically what I want to achieve with memmove
for(int i = vector->l-1; i >= 0; --i){
for(int j = vector->m; j >= 0; --j){
for(int k = vector->n; k >= 0; --k){
vector->arr[i+1][j][k] = vector->arr[i][j][k];
}
}
}
for some reason memmove shifts 2 indices.
memmove(&(vector->arr[1][1][1]), &(vector->arr[0][1][1]), (vector->l+2)*(vector->m+2)*(vector->n)*sizeof(int*));
Could anyone give me a hint?
When you create a dynamic multi-dimensional array like this, the array contents are not contiguous -- each row is a separate allocation. So you can't move it all with a single memmov().
But you don't need to copy all the data, just shift the pointers in the top-level array.
int **temp = arr[l-1]; // save last pointer, which will be overwritten
memmov(&arr[1], &arr[0], sizeof(*arr[1]));
arr[0] = temp;
I've shifted the last element around to the first, to avoid having two elements that point to the same data. You could also free the old last element (including freeing the arrays it points to) and create a new first element, but this was simpler.
Compile with a higher optimization level (-O3). Obtain a direct reference on vector->arr instead of forcing dereferencing on every single array access.
Your call to memmove looks half correct under the assumption that you allocated arr as continuous memory. However, since you said "dynamic", I very much doubt that. Plus the size calculation appears very much wrong, with the sizeof(int*).
I suppose arr is not int arr[constexpr][constexpr][constexpr] (single, continuous allocation), but rather int ***arr.
In which case the memmove goes horribly wrong. After moving the int** contents of the arr field by one (which actually already did the move), it caused a nasty overflow on the heap, most likely by chance hitting also a majority of the int* allocations following.
Looks like a double move, and leaves behind a completely destroyed heap.
Simply doing this would work (Illustrating in a 3d array)
memmove(arr[1], arr[0], Y*Z*sizeof(int));
where Y and Z denotes the other 2 dimensions of the 2d array.
Here arr[X][Y][Z] is the int array where X>=2.
In case of dynamically allocated memory you need to do each continuous chunk one by one. Then it would work.

Accessing elements in a two dimensional lattice C

Why can I not access Lattice using [ ][ ] without raising a seg fault?
int *LatticeHeight;
int **Lattice;
LatticeHeight = (int*)malloc(Height*sizeof(int));
Lattice = (int**)malloc(Length*sizeof(LatticeHeight));
for(i=0;i<Height; i++)
{
for(j=0; j<Length; j++)
{
Lattice[j][i] = 0;
}
}
I'm interpreting this as;
I have my pointer to one dimensional array of height
Then I set Lattice so that is can store Length-many copies of LatticeHeight (making a grid)
Then I access each element of the lattice and set it's value to 0
Moreover could someone explain why this works in 1D but not in 2D, i.e.
for(i=0;i<Height;i++)
{
LatticeHeight[i] = 0;
}
Does not throw a seg fault
You didn't allocate the array properly. Your first malloc allocates one row; your second malloc allocates space to store a pointer to each row but it does not actually allocate any rows to go in there (and it does not have any association to the single row you allocated earlier, either).
The simplest way to write this code, if you do not require to have rows of different lengths to each other, is to allocate a single memory block:
int (*Lattice)[Length] = calloc( Height, sizeof *Lattice );
If you do want to have a jagged array for some reason (i.e. each row is allocated in a separate memory block) then the code is:
int **Lattice = malloc( Height * sizeof *Lattice );
for ( size_t row = 0; row != Height; ++row )
Lattice[row] = calloc( Length * sizeof **Lattice );
Note that calloc allocates the memory and also zeroes it, so you don't need your zero loop afterwards, and don't cast malloc
I think you should initialize your array like this:
Lattice = (int**)malloc(Length*sizeof(int*));
for(int i = 0; i < Length; ++i) {
LatticeHeight = (int*)malloc(Height*sizeof(int));
}
You have to allocate memory for Lattice which is a pointer to a pointer to int.
Lattice = malloc(Length * sizeof(LatticeHeight));
And then iterate through the "array" of pointers to int that you just have created and allocate memory for each one, like this.
for(i = 0; i < Lenght; i++)
LatticeHeight = malloc(Height * sizeof(int));
With that you would have a two-dimensional "array".
Although, as Matt McNabb said, there are other options for what you want to do.

Scattered 2D array to contiguous 2D array transformation (in C)

I am trying to make a generic function in C that takes a 2D array of ANY type and copies it into a contiguous memory block. ( I need this function for Aggregate operations on MPI on my complex datatypes).
Imagine I have the following integer array
int n = 5;
int m = 6;
int** int_array = (int**) malloc(n* sizeof(int*));
for (int i = 0; i < n; i++ )
int_array[i] = (int *) malloc(m * sizeof(int) );
In this type of memory allocation one cannot, in principle, hope to access the , say i,j-th entry of int_array using the following pointer arithmetics
int value = (*lcc)[i*m+j];
Therefore I implemented a function that basically allocates a new memory block and neatly orders the entries of int_array so that the above indexing should work.
void linearize(char*** array, int n, int m,unsigned int size_bytes){
char* newarray = (char*)malloc(m*n*size_bytes);
//copy array!
for (int i = 0;i<n;i++)
for(int j = 0;j<m*size_bytes;j++)
{
newarray[i*m*size_bytes+j] = (*array)[i][j];
}
//swap pointers and free old memory!
for (int i = 0;i<n;i++)
{
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
}
}
I wanted to make the above function to work with any kind of array type, hence I used char pointers to do operations byte by byte. I tested the function and so far it works, but I am not sure about memory deallocation.
Does free(temp) free the whole memory pointed to by int_array[i], that is the m*sizeof(int) bytes accessible from int_array[i] or only the first m bytes (since it thinks that our array is of type char rather than in) ? Or simply put, "Does the linearize function induce any memory leaks? "
Thank you in advance!
*EDIT*
As suggested by Nicolas Barbey, I ran a valgrind checks for memory leaks and it found none.
So to summarize the main points that I found difficult to understand about the behaviour of the program were:
in the function linearize does the following code induce memory leaks:
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
NO!! somehow gnu compiler is smart enough to know how many bytes pointed to by "temp" to free. Originally I was afraid that if I array[i] is a pointer of type int , for example, that points to a memory location with say 5 ints = 5*4 bytes, the free(temp) is going to free only the first five bytes of that memory.
Another point to make is : how to free the already linearized array? that is if you have:
// first initialize the array.
int** array = (int**)malloc(5*sizeof(int*);
for(int i = 0; i< 5;i++)
array[i] = ( int* ) malloc(5*sizeof(int));
//now a call to linearize
linearize(&array,5,5,sizeof(int));
... do some work with array ....
// now time to free array
free(array[0]);
free(array);
//suffices to free all memory pointed to by array[i] and as well as the memory allocated
// for the pointers.
Thanks for the discussion and the suggestions.
You need to call free() exactly one call per malloc() inorder to be no memory leaks. Which means in your case int_array is passed to linearize function allocates a block of memory other than int_array allocation, therefore you need to loop over int_array[i] freeing each int* that you traverse followed by free'ing int_array itself. Also you need to free block created in linearize function too.
Here is a slightly slimmer version using actual two dimensional arrays:
void * linearize(void** array, int n, int m,unsigned int size_bytes){
char (*newarray)[m * size_bytes] = malloc(m*n*size_bytes);
//copy array!
int i;
for (i = 0;i<n;i++) {
memcpy(newarray[i], array[i], sizeof(*newarray));
free(array[i]);
}
free(array);
return newarray;
}
Use:
int (*newarray)[m] = linearize(array, n, m, sizeof(**int_array));
int value = newarray[i][j];
// or
value = newarray[0][i*m + j];
// or
value = ((int *)newarray)[i*m + j];

Correct way to allocate and free arrays of pointers to arrays

I want to create an array of pointers to arrays of 3 floats. What is the correct way to do this?
float *array1[SIZE]; // I think it is automatically allocated
// OR
float **array1 = calloc(SIZE, sizeof(float*));
free(array1);
for (int i = 0; i < SIZE; i++) {
array1[i] = (float[]){0,0,0};
// OR
array1[i] = calloc(3, sizeof(float));
}
Then how would I free the data? I'm pretty sure just free(array1); wouldn't work, so would I free each pointer in the array then free the array, or since I allocated three floats, would I free each float, then each 3 float array, then the whole array???
If you know the array size at compile time (and you do, if SIZE is a compile-time constant), you should just declare a two-dimensional array. You don't need to free this at all (and must not).
float array1[SIZE][3];
You need to use calloc, and to create an array of pointers, only if the dimensions are not known at compile time. In this case, there should be one call to free for each call to calloc. And since you cannot use an array after you free it, you need to free the row arrays before you free array1.
float **array1 = calloc(nrows, sizeof (float *));
for (int i=0; i < nrows; i++)
array1[i] = calloc(3, sizeof(float));
// Use it...
// Now free it
for (int i=0; i < nrows; i++)
free(array1[i]);
free(array1);
Edit: if you won't be rearranging the pointers (to sort the rows in-place, for example), you can do all of this with just one calloc (and one call to free afterwards):
float (*array1)[3] = calloc(3*nrows, sizeof (float));
That's because the number of columns is known at compile-time, and that's all the pointer arithmetic needs to know. Then you can write things like array1[i][j], and you can still pass around array1[i] as if it was a real pointer to a row. C is great that way, take advantage of it!
A general rule is that for each time you call malloc() or calloc() you will need to do a free() call on the returned pointer.
If you want a two dimensional array with compile-time known size, just use a two dimensional array! float val[5][3] is perfectly valid.
If you want a two dimensional array and you don't know it's size during compile-time, you most probably want to use a standard, single diemensional calloc() and an appropriate getter.
#define ARR_COLUMNS 10
#define ARR_ROWS 10
float* arr = calloc (ARR_COLUMNS * ARR_ROWS, sizeof(float));
int get(float* arr, int x, int y) {
if (x<0 || x>= ARR_COLUMNS) return 0;
if (y<0 || y>= ARR_ROWS) return 0;
return arr[ARR_COLUMNS*y+x];
}
void set (int* arr, int x, int y, float val) {
if (x<0 || x>= ARR_COLUMNS) return;
if (y<0 || y>= ARR_ROWS) return;
arr[ARR_COLUMNS*y+x] = val;
}
Of course replace the defines with appropriate variables.
By doing so you will:
save yourself costly allocs and frees
have less fragmented memory
simplify your possible realloc calls
ensure the data is cached better and accessed without the common [x][y] vs [y][x] iteration cache problem.
I want to create an array of pointers to arrays of 3 floats. What is the correct way to do this?
Why do you want an array of pointers to arrays? Wouldn't an array of arrays be sufficient? (Keep in mind that arrays are already pointer-like, they are not passed by value, rather the address of the first element is passed when an array is passed as an argument to a function).
// stack allocation, no need to free
float array[SIZE][3];
for (int i = 0; i < SIZE; i++) {
// do something with array[i][0], array[i][1], array[i][2]
}
Then how would I free the data?
In this case you wouldn't, since the data is stack allocated (will be cleaned up automatically once out of scope). Just remember the rule of thumb is that for every memory allocation you make, a corresponding free is necessary. So if you allocate memory for an array of floats, as in
float* arr = malloc(sizeof(float) * 3); // array of 3 floats
Then you only need to call free on the array that you malloc'd, no need to free the individual floats. If you perform nested allocation as in
// array of length SIZE, consisting of float pointers
float** arr = malloc(sizeof(float*) * SIZE);
// allocate the array of 3 floats at each index
for (int i = 0; i < SIZE; i++)
arr[i] = malloc(sizeof(float) * 3);
Then you will need to perform a free for every malloc, as in
// free the individual arrays
for (int i = 0; i < SIZE; i++)
free(arr[i]);
// free the array of arrays
free(arr);
The lesson to take away here is to avoid dynamic allocation of arrays all-together. Stick with either std::vector or stack-allocated arrays.

Resources