How to allocate a 3 dimensional array in C? [duplicate] - c

This question already has answers here:
Malloc a 3-Dimensional array in C?
(16 answers)
Closed 8 years ago.
Creating two dimensional arrays in C is easy:
char (*arr)[50] = malloc(sizeof(arr) * 10 * 50); // 10x50 matrix
How do you do three dimensional arrays in C? It doesn't look like I can do something like:
char (**arr)[50] = malloc(sizeof(arr) * 10 * 20 * 50); // 10x20x50 matrix?

Three dimensional array requires 2 dimensions to be known
char (*arr)[20][50] = malloc(sizeof(char) * 10 * 20 * 50)
Note: I have corrected sizeof(arr) to sizeof(char), because sizeof(arr) will return the size of a pointer.

A possible way could be to allocate a mono-dimensional array, e.g.
int width=10; length=20; height=50;
char* arr = malloc(width*length*height);
if (!arr) { perror("malloc"); exit(EXIT_FAILURE); };
then have some way to access it, for instance a macro
#define Element(I,J,K) arr[width*length*(I)+length*(J)+(K)]
and use Element(i,j,k)
You could pack all this using a flexible array member like
struct my3dstring_st {
int width;
int length;
int height;
char arr[];
};
then have a.g. a making function
struct my3dstring_st *
make_my3dstring (int width, int length, int height)
{
if (width<=0 || length<=0 || height<=0) return NULL;
struct my3dstring_st* s =
malloc(sizeof(struct my3dstring_st)
+ width * length * height);
if (!s) {perror("malloc"); exit(EXIT_FAILURE); };
s->width = width;
s->length = length;
s->height = height;
memset (s->arr, 0, width * length * height);
return s;
}
and an inline accessing function (in a header file):
static inline int
access_m3dstring(struct my3dstring_st*s, int i, int j, int k) {
if (!s || i<0 || j<0 || k<0
|| i>=s->width || j>=s->height || k>=s->length) return EOF;
return s->arr[i*->width*s->height + j*s->height + k];
}
I leave as an exercise to write the modification function modify_m3dstring, and you could have unsafe but faster variants which don't do any checks...

General rules:
T *arr = malloc( sizeof *arr * n ); // for an N-element array
T (*arr)[N] = malloc( sizeof *arr * m ); // for an NxM-element array
T (*arr)[N][M] = malloc( sizeof *arr * k ); // for an NxMxK-element array
where uppercase letters indicate values that are known at compile time and lowercase letters indicate values that are known at run time. The pattern for higher-dimensional arrays should be obvious.
If you are using C99 compiler or a C2011 compiler that supports variable-length arrays, you can use runtime variables for all your dimensions:
size_t n = some_value();
size_t m = some_other_value();
size_t k = yet_another_value();
T (*arr)[n][m] = malloc( sizeof *arr * k );
The type of the expression *arr is T [n][m], so sizeof *arr gives the same result as sizeof (T) * n * m; the result is easier to read and less prone to errors.
If your compiler doesn't support VLAs and you don't know your dimensions at compile time, you'll either have to allocate as a 1-d array and compute offsets manually:
T *arr = malloc( sizeof *arr * n * m * k );
...
arr[ 3*n*m + 2*m + 1] = x; // equivalient to arr[3][2][1] = x
Or, if you can live with your rows not being adjacent in memory, you could allocate the array piecemeal:
T ***arr = malloc (sizeof *arr * n );
for (size_t i = 0; i < n; i++ )
{
arr[i] = malloc( sizeof *arr[i] * m );
for (size_t j = 0; j < m; j++ )
{
arr[i][j] = malloc( sizeof *arr[i][j] * k )
}
}
Ideally, you should check the result of each malloc to make sure it succeeded. And you'll have to free the array in the reverse order that you allocated it:

char (*arr)[20][50] = malloc(sizeof(char) * 10 * 20 * 50);
sizeof(char) is guaranteed to be 1. So, it can be omitted.
char (*arr)[20][50] = malloc(10 * 20 * 50);

Related

Looping through a double pointer array and multiply or not multiply with sizeof in C?

#include <stdio.h>
#include <stdlib.h>
int main(void) {
double *array;
unsigned int size;
printf("Choose size for your number array: ");
scanf("%u", &size);
array = malloc(sizeof(double) * size);
return 0;
}
I memory allocated sizeof(double) * size, which I don't know if sizeof(double) is necessary, but sizeof(double) is not 1, so I don't know if I should either:
for (int i = 0; i < size; i++) {
}
For loop through size without multiply it with sizeof(double), or:
for (int i = 0; i < sizeof(double) * size; i++) {
}
For loop and multiply size with sizeof(double) as well? The reason why I'm asking is because I really want to be careful and prevent going over size.
For loop without multiplying sizeof(double) or not?
You allocate sizeof(double) * size memory to have array of doubles, the number of elements is size. So multiply in malloc, don't multiply in for
In this statement
array = malloc(sizeof(double) * size);
there is allocated memory for size elements with the size of objects of the type double.
You could rewrite the statement like
array = malloc( sizeof( double[size] ) );
An equivalent declaration with automatic storage duration would look like
double array[size];
if you will write (for the declaration of the array shown above with automatic or static storage duration)
printf( "sizeof( array ) = %zu\n", sizeof( array ) );
you will get a value equal to size * sizeof( double ).
So if you want to traverse all allocated elements to initialize them you should write for example
for ( int i = 0; i < size; i++ )
{
*( array + i ) = 0.0;
}
that is equivalent to
for ( int i = 0; i < size; i++ )
{
array[i] = 0.0;
}
This expression
array + i
where there is used the pointer arithmetic yields the value of pointer equal to
( double * )( ( char * )array + i * sizeof( double ) )
That is it points to the i-th element of the allocated array.
malloc(X) returns X bytes, so if you want to store size doubles, call malloc(size * sizeof(double))

Confusion with malloc. Creating an array of strings with 4 slots

int main() {
char *p[] = {"hello", "goodbye"};
char **a;
a = malloc(4 * 8);
}
I want a to have double the slots of p. How would I successfully do that without manually putting in numbers. All IK is the size of p should be there and x 2 for the double. How would I get the 8?
Using the sizeof operator which returns you the size in bytes that a
type/variable needs.
In your case
int main() {
// because "hello" and "goodbye" are const char*
const char *p[] = {"hello", "goodbye"};
size_t len_p = sizeof p / sizeof p[0];
char **a;
a = malloc( 2 * len_p * sizeof *a );
...
free(a);
}
sizeof p / sizeof p[0]; returns you the number of elements in the p array.
sizeof p returns you the total amount of bytes, sizeof p[0] returns you the
size of single element. Hence total size / size of element returns you the
number of elements. But be aware that this method only works for arrays, not
pointer. Consider this:
void add_one(int *ptr)
{
size_t len = sizeof ptr / sizeof ptr[0];
for(size_t i = 0; i < len; ++i)
ptr[i] += 1;
}
int main(void)
{
int arr[] = { 1,2 3 };
add_one(arr);
return 0;
}
is wrong, because ptr is pointer, not an array, so sizeof ptr returns you
the size of a pointer, not the total amount of bytes needed by arr. That's why
when you write a function that takes a pointer where you pass an array, the
function should also take the size of the array, otherwise the size cannot be
calculated, for example:
void add_one(int *ptr, size_t len)
{
for(size_t i = 0; i < len; ++i)
ptr[i] += 1;
}
int main(void)
{
int arr[] = { 1,2 3 };
add_one(arr, sizeof arr / sizeof arr[0]);
return 0;
}
I think what you are asking is how to figure out how many strings have been put in p. To do this, you can count the number of elements in p :
char *p[] = { "hello", "goodbye" };
printf("%zu\n", sizeof(p) / sizeof(*p));
sizeof(p) is the total size of p
sizeof(*p) is the size of a single element of p
so dividing them gives you the number of elements in p
To malloc() a second array, twice as large :
int main() {
char *p[] = { "hello", "goodbye", "lala" };
size_t size = sizeof(p) / sizeof(*p);
char **a;
a = malloc(size * 2 * sizeof(*a));
}
void allocarr(char** matrix, int bytes, int slots)
{
int i = 0;
while(i <= slots)
{
matrix[i] = (char*)calloc(1, bytes);
++i;
}
}
...
char** s = malloc(4*sizeof(char*);
s = allocarr(s, 512, 4);

How to initialize a 3D contiguous array in C

I know how to do a potentioal non-contiguous array in the following way:
int main () {
int ***array = (int***)malloc(3*sizeof(int**));
int i, j;
for (i = 0; i < 3; i++) {
// Assign to array[i], not *array[i] (that would dereference an uninitialized pointer)
array[i] = (int**)malloc(3*sizeof(int*));
for (j = 0; j < 3; j++) {
array[i][j] = (int*)malloc(3*sizeof(int));
}
}
array[1][2][1] = 10;
return 0;
}
with the code above, the array[0][j] blocks can be not contiguous. To get contiguous, I feel that we need to malloc in this way
int* array = (int*)malloc(3*3*3*sizeof(int));
int** y = (int**)malloc(3*3*sizeof(int**));
int*** x = (int***)malloc(3*sizeof(int***));
for(i = 0; i < 3; i++)
{
vals = vals + i*m*n;
x[i] = &vals;
for(j = 0; j < 3; j++)
{
x[i][j] = vals + j * n;
}
}
However, I got troulbe with address assignment. I am not a c programmer, can anyone correct my fault? Thanks in advance...
int*** x = (int***)malloc(3*sizeof(int***));
should be
int*** x = (int***)malloc(3*sizeof(int**));
Now initialization can be :
for(i = 0; i < 3; i++)
{
x[i] = y + 3*i;
for(j = 0; j < 3; j++)
{
x[i][j] = array + i*3*3 + j*3;
}
}
So that x[0] points to the first element of y, x[1] to the fourth, etc.
And x[0][0]=y[0] to the first of array, x[0][1]=y[1] to the fourth of array, etc.
To allocate a contiguous 3D array, you only need to do the following (assumes all dimensions are known at compile time):
#define D0 ...
#define D1 ...
#define D2 ...
...
T (*arr)[D1][D2] = malloc( sizeof *arr * D0 ); // for any type T
...
arr[i][j][k] = some_value();
...
arr is declared as a pointer to a D1xD2 array. We then allocate enough space for D0 such arrays (sizeof *arr == sizeof (T [D1][D2])).
With this method, all of the memory for the array is allocated contiguously. Also, you only need one call to free to deallocate the whole thing.
If your dimensions are not known until runtime and you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you're still in luck:
size_t d0, d1, d2;
...
T (*arr)[d1][d2] = malloc( sizeof *arr * d0 );
The main issue is how to pass this as an argument to a function. Assuming that D1 and D2 are known at compile time, if you decide to pass it as
foo( arr, D0 );
then the prototype for foo will need to be
void foo( T (*aptr)[D1][D2], size_t n )
{
...
aptr[i][j][k] = ...;
}
and it will only be useful for n x D1 x D2-sized arrays.
If you go the VLA route, you'll need to declare the dimensions and pass values for them as well:
void foo( size_t d0, size_t d1, size_t d2, T (*aptr)[d1][d2] ) // d1 and d2 *must* be
// declared before aptr
{
...
arr[i][j][k] = some_value();
}
void bar( void )
{
size_t d0, d1, d2;
...
T (*arr)[d1][d2] = malloc( sizeof *arr * d0 );
...
foo( d0, d1, d2, arr );
...
}
If you don't have a compiler that supports VLAs, but you still want to allocate this memory contiguously, then you'll have to go the old-fashioned route - allocate it as a 1D array and compute your offsets manually:
T *arr = malloc( sizeof *arr * d0 * d1 * d2 );
...
arr[i * d0 * d1 + j * d1 + k] = some_value();
I am using some pretty neat methods for allocating multi-dimensional arrays with row pointers. The functions multi_malloc and multi_free can be used for arrays with arbitrary dimensions and arbitrary types and they work on basically all platforms and from C and C++
You can allocate, e.g. a 3-dimensional array with row-pointers recursively. E.g. a 10x20x30 dimensional array
float*** data = (float***) multi_malloc(sizeof(float),3, 10,20,20);
access elements like
data[2][3][4] = 2.0;
and free everything like (data as well as row pointers)
multi_free(data,3);
The header, which I think should be part of C is
#pragma once
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#if (defined(_MSC_VER) && defined(_WIN32))
// Note when used inside a namespace, the static is superfluous
# define STATIC_INLINE_BEGIN static inline //__forceinline
# define STATIC_INLINE_END
#elif (defined(__GNUC__))
# define STATIC_INLINE_BEGIN static inline
# if defined(__CYGWIN__)
# define STATIC_INLINE_END
# else
# define STATIC_INLINE_END __attribute__ ((always_inline))
# endif
#endif
STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) STATIC_INLINE_END;
STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) STATIC_INLINE_END;
/**
* Allocate multi-dimensional array and establish row pointers
*
* #param s size of each element
* #param d number of dimension
*
* #return
*/
STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) {
char* tree;
va_list ap; /* varargs list traverser */
size_t max, /* size of array to be declared */
*q; /* pointer to dimension list */
char **r, /* pointer to beginning of the array of the
* pointers for a dimension */
**s1, *t; /* base pointer to beginning of first array */
size_t i, j; /* loop counters */
size_t *d1; /* dimension list */
va_start(ap,d);
d1 = (size_t *) malloc(d*sizeof(size_t));
for(i=0;i<d;i++)
d1[i] = va_arg(ap,size_t);
r = &tree;
q = d1; /* first dimension */
if (d==1) {
max = *q;
free(d1);
return malloc(max*d);
}
max = 1;
for (i = 0; i < d - 1; i++, q++) { /* for each of the dimensions
* but the last */
max *= (*q);
r[0]=(char *)malloc(max * sizeof(char **));
r = (char **) r[0]; /* step through to beginning of next
* dimension array */
}
max *= s * (size_t) (*q); /* grab actual array memory */
r[0] = (char *)malloc(max * sizeof(char));
/*
* r is now set to point to the beginning of each array so that we can
* use it to scan down each array rather than having to go across and
* then down
*/
r = (char **) tree; /* back to the beginning of list of arrays */
q = d1; /* back to the first dimension */
max = 1;
for (i = 0; i < d - 2; i++, q++) { /* we deal with the last
* array of pointers later on */
max *= (*q); /* number of elements in this dimension */
for (j=1, s1=r+1, t=r[0]; j<max; j++) { /* scans down array for
* first and subsequent
* elements */
/* modify each of the pointers so that it points to
* the correct position (sub-array) of the next
* dimension array. s1 is the current position in the
* current array. t is the current position in the
* next array. t is incremented before s1 is, but it
* starts off one behind. *(q+1) is the dimension of
* the next array. */
*s1 = (t += sizeof (char **) * *(q + 1));
s1++;
}
r = (char **) r[0]; /* step through to begining of next
* dimension array */
}
max *= (*q); /* max is total number of elements in the
* last pointer array */
/* same as previous loop, but different size factor */
for (j = 1, s1 = r + 1, t = r[0]; j < max; j++)
*s1++ = (t += s * *(q + 1));
va_end(ap);
free(d1);
return((void *)tree); /* return base pointer */
}
/**
* Free multi-dimensional array and corresponding row pointers
*
* #param r data
* #param d number of dimensions
*/
STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) {
void **p;
void *next=NULL;
size_t i;
for (p = (void **)r, i = 0; i < d; p = (void **) next,i++)
if (p != NULL) {
next = *p;
free(p);
p = NULL;
}
}
You can allocate memory for buffer of items where each item is a two dimensional array. So it is effectively is a three dimensional array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
int main()
{
int (*array)[N][N] = malloc(N * N * N * sizeof(int));
/* set 0 to all values */
memset(array, 0, N * N * N * sizeof(int));
/* use as 3D array */
array[0][0][0] = 1;
array[1][1][1] = 2;
array[2][2][2] = 3;
int i;
/* print array as contiguous buffer */
for (i = 0; i < N * N * N; ++i)
printf("i: %d\n", ((int*) array)[i]);
free(array);
return 0;
}
So, in memory the array is placed as regular int array[N][N][N].
Although I think a normal array, created on the stack would be best:
int array[3][3][3];//can avoid a lot of free() calls later on
Here is a way to create a 3D array dynamically:
(I use calloc here instead of malloc as it creates initialized memory space)
int *** Create3D(int p, int c, int r)
{
int ***arr;
int x,y;
arr = calloc(p, sizeof(arr)); //memory for int
for(x = 0; x < p; x++)
{
arr[x] = calloc(c ,sizeof(arr)); //memory for pointers
for(y = 0; y < c; y++)
{
arr[x][y] = calloc(r, sizeof(int));
}
}
return arr;
}
Usage could be:
int ***array = Create3D(3,3,3);
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
array[i][j][k] = (i+1)*(j+1)*(k+1);
Note that the return of [c][m][re]alloc() is not cast in this example. Although not strictly forbidden in C, it is not recommended. (this is not the case in C++, where it is required)
Keep in mind, everything allocated, must be freed. Notice freeing is done in reverse order of allocating:
void free3D(int ***arr, int p, int c)
{
int i,j;
for(i=0;i<p;i++)
{
for(j=0;j<c;j++)
{
if(arr[i][j]) free(arr[i][j]);
}
if(arr[i]) free(arr[i]);
}
if(arr) free(arr);
}
Usage could be:
free3D(array,3,3);

Assign Memory to 3D array using triple pointer

I have to assign memory to a 3D array using a triple pointer.
#include <stdio.h>
int main()
{
int m=10,n=20,p=30;
char ***z;
z = (char***) malloc(sizeof(char**)*m*n*p);
return 0;
}
Is this correct way of doing this?(I think what i am doing is incorrect.)
To completely allocate a 3D dynamic array you need to do something like the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m=10,n=20,p=30;
char ***z;
z = malloc(m * sizeof(char **));
assert(z != NULL);
for (i = 0; i < m; ++i)
{
z[i] = malloc(n * sizeof(char *));
assert(z[i] != NULL);
for (j = 0; j < n; ++j)
{
z[i][j] = malloc(p);
assert(z[i][j] != NULL);
}
}
return 0;
}
Freeing the data is left as an exercise for the reader.
There's no need to cast the return value of malloc(), in C.
And if you expect to store m * n * p characters directly (and compute the address yourself), then you should of course not scale the allocation by the size of a char **.
You mean:
int m = 10, n = 20, p = 30;
char *z = malloc(m * n * p * sizeof *z);
This will allocate 10 * 20 * 30 = 6000 bytes. This can be viewed as forming a cube of height p, with each "slice" along the vertical axis being n * m bytes.
Since this is for manual addressing, you cannot use e.g. z[k][j][i] to index, instead you must use z[k * n * m + j * m + i].
If you don't need the memory to be allocated in a single, contiguous chunk (which IME is the usual case), you would do something like this:
char ***z;
z = malloc(sizeof *z * m); // allocate m elements of char **
if (z)
{
int i;
for (i = 0; i < m; i++)
{
z[i] = malloc(sizeof *z[i] * n); // for each z[i],
if (z[i]) // allocate n elements char *
{
int j;
for (j = 0; j < n;j++)
{
z[i][j] = malloc(sizeof *z[i][j] * p); // for each z[i][j],
if (z[i][j]) // allocate p elements of char
{
// initialize each of z[i][j][k]
}
}
}
}
}
Note that you will need to free this memory in reverse order:
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
free(z[i][j];
free(z[i]);
}
free(z);
If you really need the memory to be allocated in a contiguous chunk, you have a couple of choices. You could allocate a single block and compute your offsets manually:
char *z = malloc(sizeof *z * m * n * p); // note type of z!
...
z[i * m + j * n + k] = some_value();
When you're done, you just need to do a single free:
free(z);
If you have a C99 compiler or a C11 compiler that supports variable-length arrays, you could do something like this:
int m=..., n=..., p=...;
char (*z)[n][p] = malloc(sizeof *z * m);
This declares z as a pointer to an nxp array of char, and we allocate m such elements. The memory is allocated contiguously and you can use normal 3-d array indexing syntax (z[i][j][k]). Like the above method, you only need a single free call:
free(z);
If you don't have a C99 compiler or a C11 compiler that supports VLAs, you would need to make n, and p compile-time constants, such as
#define n 20
#define p 30
otherwise that last method won't work.
Edit
m doesn't need to be a compile-time constant in this case, just n and p.
You would need the following nested loop -
z = (char**)malloc(sizeof(char*) * m);
for (int i = 0; i < m; ++i)
{
*(z + i) = (char*)malloc(sizeof(char*) * n);
for (int j = 0; j < n; ++j)
{
*(*(z + i)) = (char)malloc(p);
}
}
May not be synactically accurate, but it should be something along these lines.
You want sizeof(char) not sizeof(char**) as the latter will give you the size of a pointer which on most modern systems will be 4 bytes instead of the 1 you're expecting.

dynamic allocating array of arrays in C

I don't truly understand some basic things in C like dynamically allocating array of arrays.
I know you can do:
int **m;
in order to declare a 2 dimensional array (which subsequently would be allocated using some *alloc function). Also it can be "easily" accessed by doing *(*(m + line) + column). But how should I assign a value to an element from that array? Using gcc the following statement m[line][column] = 12; fails with a segmentation fault.
Any article/docs will be appreciated. :-)
The m[line][column] = 12 syntax is ok (provided line and column are in range).
However, you didn't write the code you use to allocate it, so it's hard to get whether it is wrong or right. It should be something along the lines of
m = (int**)malloc(nlines * sizeof(int*));
for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));
Some side-notes:
This way, you can allocate each line with a different length (eg. a triangular array)
You can realloc() or free() an individual line later while using the array
You must free() every line, when you free() the entire array
Your syntax m[line][colummn] is correct. But in order to use a 2D array in C, you must allocate memory for it. For instance this code will allocated memory for a table of given line and column.
int** AllocateArray(int line, int column) {
int** pArray = (int**)malloc(line*sizeof(int*));
for ( int i = 0; i < line; i++ ) {
pArray[i] = (int*)malloc(column*sizeof(int));
}
return pArray;
}
Note, I left out the error checks for malloc for brevity. A real solution should include them.
It's not a 2d array - it's an array of arrays - thus it needs the multiple allocations.
Here's a modified version of quinmars' solution which only allocates a single block of memory and can be used with generic values by courtesy of void *:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void ** array2d(size_t rows, size_t cols, size_t value_size)
{
size_t index_size = sizeof(void *) * rows;
size_t store_size = value_size * rows * cols;
char * a = malloc(index_size + store_size);
if(!a) return NULL;
memset(a + index_size, 0, store_size);
for(size_t i = 0; i < rows; ++i)
((void **)a)[i] = a + index_size + i * cols * value_size;
return (void **)a;
}
int printf(const char *, ...);
int main()
{
int ** a = (int **)array2d(5, 5, sizeof(int));
assert(a);
a[4][3] = 42;
printf("%i\n", a[4][3]);
free(a);
return 0;
}
I'm not sure if it's really safe to cast void ** to int ** (I think the standard allows for conversions to take place when converting to/from void * ?), but it works in gcc. To be on the safe side, you should replace every occurence of void * with int * ...
The following macros implement a type-safe version of the previous algorithm:
#define alloc_array2d(TYPE, ROWS, COLS) \
calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1)
#define init_array2d(ARRAY, TYPE, ROWS, COLS) \
do { for(int i = 0; i < ROWS; ++i) \
ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \
i * COLS * sizeof(TYPE)); } while(0)
Use them like this:
int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;
Although I agree with the other answers, it is in most cases better to allocate the whole array at once, because malloc is pretty slow.
int **
array_new(size_t rows, size_t cols)
{
int **array2d, **end, **cur;
int *array;
cur = array2d = malloc(rows * sizeof(int *));
if (!array2d)
return NULL;
array = malloc(rows * cols * sizeof(int));
if (!array)
{
free(array2d);
return NULL;
}
end = array2d + rows;
while (cur != end)
{
*cur = array;
array += cols;
cur++;
}
return array2d;
}
To free the array simply do:
free(*array); free(array);
Note: this solution only works if you don't want to change the order of the rows, because you could then lose the address of the first element, which you need to free the array later.
Humm. How about old fashion smoke and mirrors as an option?
#define ROWS 5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))
int main(void)
{
int *p = (int *) malloc (ROWS * COLS * sizeof(int));
if (p != NULL)
{
size_t r;
size_t c;
for (r = 0; r < ROWS; r++)
{
for (c = 0; c < COLS; c++)
{
X(r,c) = r * c; /* put some silly value in that position */
}
}
/* Then show the contents of the array */
for (r = 0; r < ROWS; r++)
{
printf("%d ", r); /* Show the row number */
for (c = 0; c < COLS; c++)
{
printf("%d", X(r,c));
}
printf("\n");
}
free(p);
}
else
{
/* issue some silly error message */
}
return 0;
}
Using malloc(3) for allocate the first array and putting in there pointers created by malloc(3) should work with array[r][c] because it should be equivalent to *(*(array + r) + c), it is in the C standard.

Resources