General two-dimensional array

I want to create a two-dimensional array as follows:

void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement) { int i; void **m = malloc(nrLini * 4); if(m==NULL) return NULL; for(i=0; i<nrLini; i++) { *(m + (i*4)) = malloc(nrColoane * sizeOfElement); if(*(m + (i*4)) == NULL) return NULL; } return m; } 

I want to use it like this:

 int **m = (int **)mdeclaraMatrice(n,m,sizeof(int)); 

but that will not work. What am I doing wrong?

+7
c
source share
5 answers

You should use m[i] instead of *(m+i*4) and let the compiler do arithmetic.

In addition, you must free up already allocated memory in the event of a failure.

Try instead:

 void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement) { int i; void **m = malloc(nrLini * sizeof(void*)); if (m == NULL) return NULL; for (i=0; i<nrLini; i++) { m[i] = malloc(nrColoane * sizeOfElement); if (m[i] == NULL) { while (i-- > 0) free(m[i]); free(m); return NULL; } } return m; } 
+5
source share

[not the answer to the question, but indented using the correct answer, as indicated by others)

To access the void pointer array as an int array by doing this

 int **m = (int **)mdeclaraMatrice(n,m,sizeof(int)); 

incorrect, since only C-Standard void* correctly converted to any other pointer, void** not necessary. Therefore he must be

 void ** ppv = mdeclaraMatrice(n,m,sizeof(int)); int * pi = *ppv; /* Please note, there is NO casting necessary here! */ 

Then access the items as follows:

 pi[0] = 42 pi[1] = 43; ... 

This is essentially the same as doing

 *((int *) (pi + 0)) = 42; *((int *) (pi + 1)) = 43; 

which really doesn't make sense, since pi already int* , so a completely correct approach (also taking into account the 2nd dimension) would be as follows:

 ((int *)(ppv[0]))[0] = 42; ((int *)(ppv[0]))[1] = 43; 

What can be made usable by discarding the macro:

 #define GENERIC_ARRAY_ELEMENT(type, address, r, c) \ ((type *)(address[r]))[c] GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42; GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43; 
+4
source share

I will consider the problem of allocating an array of void pointers and then interpret them as an array of int pointers.

 int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int)); 

Even assuming the distribution was completely correct, the purpose and subsequent use of nope is undefined behavior. void** and int** have incompatible types.

What you can do is the following. Assign void pointers one after another to an array of int pointers.

 void** arrp = mdeclaraMatrice(n,m,sizeof(int)); int* arr[n] ; for( size_t i = 0 , i < n ; i++ ) arr[i] = arrp[i] ; 

And then use the arr array. If you want to free memory, you free the original pointer:

 free( arrp ) ; 
+3
source share

The problem occurs on this line:

 *(m + (i*4)) = malloc(nrColoane * sizeOfElement); 

You should know that when adding a number to an address, the address will be increased by the number of times the size of the object that the address points to. Therefore, if your pointer points to an object of size 4 bytes and you add 1 to it, then the address will automatically be increased by 4, not by 1. Thus, you must refuse *4 .

In addition, the sizeof operator is used when allocating space, because addresses (and therefore pointers) can have different sizes on different processor architectures.

+2
source share

In fact, you donโ€™t even need your general 2D array function if you know the powerful VLA C99 functions. To select a true 2D array (no index array required), you simply do the following:

 int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray)); 

What is it. Access is simple:

 twoDIntArray[line][column] = 42; 

In this code, twoDIntArray is a pointer to an array of integers width . The malloc() call simply allocates enough space for the height such linear arrays. When you do twoDIntArray[line] pointer arithmetic, you add the size of the line array to the pointer, which returns the address of the corresponding line array. This row array is then indexed by the second index of the [column] array.

Needless to say, freeing such an array is equally trivial:

 free(twoDIntArray); 
+2
source share

All Articles