Declaring a two-dimensional array of unknown size, C

I have an array declared as a member of a structure in C. An array is declared as:

char mValue[MAXROWS][MAXCOLUMNS]; 

where are MAXROWS and MAXROWS - 300. Is there a better way to do this? I mean, should they be declared as pointers instead?

Thanks!

+4
source share
6 answers

As the previous poster showed, a good way is to create a linear array and then "convert it to 2D." Caching two-dimensional pointers many times significantly increases the speed of programs that use this array, for example:

 mystruct *p = (mystruct*)calloc(ROWS * COLUMNS, sizeof(mystruct)); mystruct **p2 = (mystruct**)calloc(ROWS, sizeof(mystruct*)); for (int i = 0; i < ROWS; i++) p2[i] = p + i*COLUMNS; 

Then you can simply access the two-dimensional element with:

 p2[row][column] = foo; 
+2
source

If all your lines are the same size, you should use a 1D array with the lines stored in sequence:

 ABCDE FGHIJ ---> ABCDEFGHIJKLMNO KLMNO 

The element in row i, column j will have the index i * ROW_LENGTH + j in the 1D array.

You can allocate an array using malloc(ROW_LENGTH * NUM_ROWS) .

+2
source

Another method is to create a linear array and then convert it to 2d:

 char *p = malloc(ROWS * COLUMNS); // To access x, y // This is in row-major ordr *(p + (x * COLUMNS) + y); 
+1
source

I find that for this type of code it is better to create helper functions to access the elements. Depending on your profiling data, it may make sense to turn them into macros, but be careful.

 #include <stdio.h> /* For printf */ /* This is the bit that would go in a header, like char2darray.h */ #include <stdlib.h> /* For calloc */ #include <assert.h> /* For assert */ struct Char2DArray { int rows; int columns; char *values; }; /* This is the bit that would go in a source file, like char2darray.c */ void C2DA_initialize(struct Char2DArray *array, int rows, int columns) { assert(array != 0); array->values = calloc(rows * columns, sizeof(char)); array->rows = rows; array->columns = columns; } void C2DA_set(struct Char2DArray *array, int row, int column, int value) { assert(array != 0); assert(array->values != 0); assert(row < array->rows); assert(row >= 0); assert(column < array->columns); assert(column >= 0); array->values[(row * array->rows) + column] = value; } char C2DA_get(struct Char2DArray *array, int row, int column) { assert(array != 0); assert(array->values != 0); assert(row < array->rows); assert(row >= 0); assert(column < array->columns); assert(column >= 0); return array->values[(row * array->rows) + column]; } void C2DA_free(struct Char2DArray *array) { free(array->values); array->values = 0; } /* Here a main.c to use it */ int main() { struct Char2DArray a; C2DA_initialize(&a, 16, 16); unsigned char c = 0; int x, y; for (x=0; x<16; x++) { for (y=0; y<16; y++) { C2DA_set(&a, x, y, (char)c); c++; } } printf("Character with hex value 0x55 is %c\n", C2DA_get(&a, 5, 5)); C2DA_free(&a); return 0; } 
+1
source

If the array must have a dynamic size, you need to either make it a pointer, or make the array the last member of the structure and games when distributing the size of the structure.

Relevant entries in comp.lang.c:

0
source

I found that changing my approach was very helpful when faced with a similar problem.

The vector of vectors filled the same task, avoided the obstacles of memory allocation, and kept the same familiar shorthand. There may be other pitfalls, but I have not met them yet.

 //Declaration of mValues, undefined size: std::vector< std::vector<char> > mValues; //Filling of mValues: int max_x = 100 ; int max_y = 100 ; char char_foo = 'a'; for ( int x = 0; x <= max_x; ++x ) { vector<char> temp; for ( int y = 0; y <= max_y; ++y ) { temp.push_back( char_foo ); } mValues.push_back( temp ); } // Referencing with familiar index notation: mValues[a][b]; //The a-th row b-th element 

If you're struggling with arrays but really want a familiar indexing language, I found this to be a good alternative.

Note that indexing order A then B will be critical for memory usage when calling this data. Non-compliance with information in order A, B will be very problematic if performance is a problem.

0
source

Source: https://habr.com/ru/post/1313456/


All Articles