I am trying to create a two dimensional array based on two pre-calculated values (here len1 and len2 are const, but they come from another function). When I run this I get segmentation fault. I am very new to C, this is my first task. Can not figure it out from Guides nor SO, anybody around to help me out?
I suppose the dynamic creation of the two dimensional arrays is wrong. But can't find a good example that would work ..
int main() {
int y, x;
int my_val = 10; // dynamnic value calculated by another func
int len1 = 3; // dynamnic value calculated by another func
int len2 = 3; // dynamnic value calculated by another func
int cols = len1 + 1;
int rows = len2 + 1;
int **twodarr = (int **)malloc(rows * cols * sizeof(int));
for (x = 1; x < cols; x++) {
for (y = 1; y < rows; y++) {
twodarr[y][x] = my_val;
}
}
return 0;
}
Arrays have never been first class elements in C, and multi-dimensional ones have even more poor support. Originally, only C used constant sized arrays, because pointer arithmetics was enough for dynamic 1D arrays, and pointers were an essential element of the language.
C99 introduced the concept of Variable Length Arrays which are what #Lundin's answer uses. Unfortunately, C11 defined them as an optional feature, and Microsoft choosed not to support them for compatibility with C++.
If you use a Microsoft compiler or want compability with environments that do not support the optional VLA feature, you will have to use the old linear idiom: you only use 1D arrays and use compound indices computation: the index of element (i, j) is j + i * cols where cols is the size of the second dimension.
Your code could become:
...
int *twodarr = malloc(rows * cols * sizeof(int)); // BEWARE: actualy 1D array!
for (x = 1; x < cols; x++) {
for (y = 1; y < rows; y++) {
twodarr[x + y*cols] = my_val;
}
}
...
You have to allocate each rows
// allocation of cols
int **twodarr = (int **)malloc(cols * sizeof(int*));// note it is sizeof(int*)
// allocation each rows (in each cols)
for (x = 0; x < cols; x++) {
twodarr[x] = (int *)malloc(rows * sizeof(int));
}
The problem is that int **twodarr cannot be used for 2D arrays, it has no relation what-so-ever to them. You need to swap it for a pointer to a 2D array. Or more conveniently, a pointer to a 1D array - a pointer to a row in this case, assuming [rows][cols].
Also, arrays in C start at index 0.
Code with bug fixes & a simple print example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int my_val = 10; // dynamnic value calculated by another func
int len1 = 3; // dynamnic value calculated by another func
int len2 = 3; // dynamnic value calculated by another func
int rows = len2 + 1;
int cols = len1 + 1;
int (*twodarr)[cols] = malloc( sizeof(int[rows][cols]) );
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
twodarr[r][c] = my_val;
printf("%d ", twodarr[r][c]);
}
puts("");
}
free(twodarr);
return 0;
}
#kcabus had it right...and admittedly the much more readable way for sanity sake.
The other way to go about it would be to declare it as a memory block, but its much more confusing.
such as
int *twodarr = (int*)calloc((rows *
cols), sizeof(int));
// accessed as follows
*(twodarr + rows*r + c) = value;
// rows * position + position 2
// much more confusing.
A third alternative would be to create a struct like POINT (or just use point) and use two values by just creating an array of POINT just as an example. But I assume you don't want to deal with that in a loop...and I don't blame you heh.
Related
I dynamically allocated memory for 3D array of pointers. My question is how many pointers do I have? I mean, do I have X·Y number of pointers pointing to an array of double or X·Y·Z pointers pointing to a double element or is there another variant?
double*** arr;
arr = (double***)calloc(X, sizeof(double));
for (int i = 0; i < X; ++i) {
*(arr + i) = (double**)calloc(Y, sizeof(double));
for (int k = 0; k < Y; ++k) {
*(*(arr+i) + k) = (double*)calloc(Z, sizeof(double));
}
}
The code you apparently intended to write would start:
double ***arr = calloc(X, sizeof *arr);
Notes:
Here we define one pointer, arr, and set it to point to memory provided by calloc.
Using sizeof (double) with this is wrong; arr is going to point to things of type double **, so we want the size of that. The sizeof operator accepts either types in parentheses or objects. So we can write sizeof *arr to mean “the size of a thing that arr will point to”. This always gets the right size for whatever arr points to; we never have to figure out the type.
There is no need to use calloc if we are going to assign values to all of the elements. We can use just double ***arr = malloc(X * sizeof *arr);.
In C, there is no need to cast the return value of calloc or malloc. Its type is void *, and the compiler will automatically convert that to whatever pointer type we assign it to. If the compiler complains, you are probably using a C++ compiler, not a C compiler, and the rules are different.
You should check the return value from calloc or malloc in case not enough memory was available. For brevity, I omit showing the code for that.
Then the code would continue:
for (ptrdiff_t i = 0; i < X; ++i)
{
arr[i] = calloc(Y, sizeof *arr[i]);
…
}
Notes:
Here we assign values to the X pointers that arr points to.
ptrdiff_t is defined in stddef.h. You should generally use it for array indices, unless there is a reason to use another type.
arr[i] is equivalent to *(arr + i) but is generally easier for humans to read and think about.
As before sizeof *arr[i] automatically gives us the right size for the pointer we are setting, arr[i].
Finally, the … in there is:
for (ptrdiff_t k = 0; k < Y; ++k)
arr[i][k] = calloc(Z, sizeof *arr[i][k]);
Notes:
Here we assign values to the Y pointers that arr[i] points to, and this loop is inside the loop on i that executes X times, so this code assigns XY pointers in total.
So the answer to your question is we have 1 + X + XY pointers.
Nobody producing good commercial code uses this. Using pointers-to-pointers-to-pointers is bad for the hardware (meaning inefficient in performance) because the processor generally cannot predict where a pointer points to until it fetches it. Accessing some member of your array, arr[i][j][k], requires loading three pointers from memory.
In most C implementations, you can simply allocate a three-dimensional array:
double (*arr)[Y][Z] = calloc(X, sizeof *arr);
With this, when you access arr[i][j][k], the compiler will calculate the address (as, in effect, arr + (i*Y + j)*Z + k). Although that involves several multiplications and additions, they are fairly simple for modern processors and are likely as fast or faster than fetching pointers from memory and they leave the processor’s load-store unit free to fetch the actual array data. Also, when you are using the same i and/or j repeatedly, the compiler likely generates code that keeps i*Y and/or (i*Y + j)*Z around for multiple uses without recalculating them.
Well, short answer is: it is not known.
As a classic example, keep in mind the main() prototype
int main( int argc, char** argv);
argc keeps the number of pointers. Without it we do not know how many they are. The system builds the array argv, gently updates argc with the value and then launches the program.
Back to your array
double*** arr;
All you know is that
arr is a pointer.
*arr is double**, also a pointer
**arr is double*, also a pointer
***arr is a double.
What you will get in code depends on how you build this. A common way if you need an array of arrays and things like that is to mimic the system and use a few unsigned and wrap them all with the pointers into a struct like
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
A CSV file for example is char ** **, a sheet workbook is char ** ** ** and it is a bit scary, but works. For each ** a counter is needed, as said above about main()
A C example
The code below uses arr, declared as double***, to
store a pointer to a pointer to a pointer to a double
prints the value using the 3 pointers
then uses arr again to build a cube of X*Y*Z doubles, using a bit of math to set values to 9XY9.Z9
the program uses 2, 3 and 4 for a total of 24 values
lists the full array
list the first and the very last element, arr[0][0][0] and arr[X-1][Y-1][Z-1]
frees the whole thing in reverse order
The code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
int print_array(double***, int, int, int);
int main(void)
{
double sample = 20.21;
double* pDouble = &sample;
double** ppDouble = &pDouble;
double*** arr = &ppDouble;
printf("***arr is %.2ff\n", ***arr);
printf("original double is %.2ff\n", sample);
printf("*pDouble is %.2ff\n", *pDouble);
printf("**ppDouble is %.2ff\n", **ppDouble);
// but we can build a cube of XxYxZ doubles for arr
int X = 2;
int Y = 3;
int Z = 4; // 24 elements
arr = (double***)malloc(X * sizeof(double**));
// now each arr[i] must point to an array of double**
for (int i = 0; i < X; i += 1)
{
arr[i] = (double**)malloc(Y * sizeof(double*));
for (int j = 0; j < Y; j += 1)
{
arr[i][j] = (double*)malloc(Z * sizeof(double));
for (int k = 0; k < Z; k += 1)
{
arr[i][j][k] = (100. * i) + (10. * j) + (.1 * k) + 9009.09;
}
}
}
print_array(arr, X, Y, Z);
printf("\n\
Test: first element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n\
last element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n",
0, 0, 0, arr[0][0][0],
(X-1), (Y-1), (Z-1), arr[X-1][Y-1][Z-1]
);
// now to free this monster
for (int x = 0; x < X; x += 1)
{
for (int y = 0; y < Y; y += 1)
{
free(arr[x][y]); // the Z rows
}
free(arr[x]); // the plane Y
}
free(arr); // the initial pointer;
return 0;
}; // main()
int print_array(double*** block, int I, int J, int K)
{
for (int a = 0; a < I; a += 1)
{
printf("\nPlane %d\n\n", a);
for (int b = 0; b < J; b += 1)
{
for (int c = 0; c < K; c += 1)
{
printf("%6.2f ", block[a][b][c]);
}
printf("\n");
}
}
return 0;
}; // print_array()
The output
***arr is 20.21f
original double is 20.21f
*pDouble is 20.21f
**ppDouble is 20.21f
Plane 0
9009.09 9009.19 9009.29 9009.39
9019.09 9019.19 9019.29 9019.39
9029.09 9029.19 9029.29 9029.39
Plane 1
9109.09 9109.19 9109.29 9109.39
9119.09 9119.19 9119.29 9119.39
9129.09 9129.19 9129.29 9129.39
Test: first element is arr[0][0[0] = 9009.09 (9XY9.Z9)
last element is arr[1][2[3] = 9129.39 (9XY9.Z9)
I created two 2D arrays (matrix) in C in two different ways.
I don't understand the difference between the way they're represented in the memory, and the reason why I can't refer to them in the same way:
scanf("%d", &intMatrix1[i][j]); //can't refer as &intMatrix1[(i * lines)+j])
scanf("%d", &intMatrix2[(i * lines)+j]); //can't refer as &intMatrix2[i][j])
What is the difference between the ways these two arrays are implemented and why do I have to refer to them differently?
How do I refer to an element in each of the arrays in the same way (?????? in my printMatrix function)?
int main()
{
int **intMatrix1;
int *intMatrix2;
int i, j, lines, columns;
lines = 3;
columns = 2;
/************************* intMatrix1 ****************************/
intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
for (i = 0; i < lines; ++i)
{
for (j = 0; j < columns; ++j)
{
printf("Type a number for intMatrix1[%d][%d]\t", i, j);
scanf("%d", &intMatrix1[i][j]);
}
}
/************************* intMatrix2 ****************************/
intMatrix2 = (int *)malloc(lines * columns * sizeof(int));
for (i = 0; i < lines; ++i)
{
for (j = 0; j < columns; ++j)
{
printf("Type a number for intMatrix2[%d][%d]\t", i, j);
scanf("%d", &intMatrix2[(i * lines)+j]);
}
}
/************** printing intMatrix1 & intMatrix2 ****************/
printf("intMatrix1:\n\n");
printMatrix(*intMatrix1, lines, columns);
printf("intMatrix2:\n\n");
printMatrix(intMatrix2, lines, columns);
}
/************************* printMatrix ****************************/
void printMatrix(int *ptArray, int h, int w)
{
int i, j;
printf("Printing matrix...\n\n\n");
for (i = 0; i < h; ++i)
for (j = 0; j < w; ++j)
printf("array[%d][%d] ==============> %d\n, i, j, ??????);
}
You are dereferencing the Matrix1 two times..
Matrix1[i][j] ;
It means that it is a 2D array or a double pointer declared like this.
int **Matrix1 ;
A double pointer could be thought of as array of pointers. Its each element is a pointer itself, so it is dereferenced once to reach at the pointer element, and dereferenced twice to access the data member of that member pointer or array. This statement as you you wrote is equivalent to this one..
Matrix1[i][j] ; //is ~ to
*( *(Matrix1 + i) + j) ;
For a single pointer like this.
int *Matrix2 ;
You can derefernce it only once, like this.
Matrix2[i] ; //is ~ to
*(Matrix2 + i) ;
This statement which you wrote..
Matrix2[(i * lines)+j] ;
|-----------|
This portion evaluates to a single number, so it derefenced one time.
(i * lines) + j ;
As for your printmatrix() function, the ptArray passed to it is a single pointer. So you cannot dereference it twice.
Perhaps you can get better understanding of static and dynamic 2D arrays from my answer here.
2D-array as argument to function
Both matrices are sequences of bytes in memory. However, the difference between them is how you're defining the memory interface to represent a matrix. In one case you're just defining a memory segment with a number of elements equal to the elements in the matrix, and in the other case you're specifically allocating memory to represent each specific line.
The following case is more expensive computationally, because you're invoking malloc() a greater number of times:
intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
However, it brings the advantage that you get to refer to matrix elements in a clearer fashion:
intMatrix1[i][j];
If you just allocate one sequence of elements equal to the number of elements in the matrix, you have to take in account line/column index calculations to refer to the right matrix elements in memory.
To attempt to increase the degree of uniformity in the code, may I suggest a function that receives the matrix line reference and matrix column-count and prints a line?
void PrintLine(int *ptrLine, int lineLen) {
unsigned int i;
for(i = 0; i < lineLen; i++)
printf("%d ", ptrLine[i]);
printf("\n");
}
And then, for each matrix type, you would just do:
// Case 1
for(i = 0; i < lines; i++)
PrintLine(intMatrix1[i], columns);
// Case 2
for(i = 0; i < lines; i++) {
PrintLine(intMatrix2 + i*columns, columns);
}
In C, the array access operator [] is really just a cleaner way of performing pointer arithmetic. For a one-dimensional array of elements of type type_s, arr[i] is equivalent to *(arr + (i * sizeof(type_s))). To dissect that expression:
arr will be the base address, the lowest memory address where this array is stored
i is the zero-indexed position of the element in the array
sizeof returns the number of chars (which is generally the same as the number of bytes, but it's not mandated by the C spec) that an element in arr takes up in memory. The compiler will determine the size of the element and take care of performing this math for you.
As a side note, this syntax has the side effect of arr[i] being equivalent to i[arr], although it's universally accepted to put the index in brackets.
So with all of that said, let's look at the differences between your two declarations:
intMatrix1[i][j] is equivalent to *(*(intMatrix1 + i * sizeof(int)) + j * sizeof(int)). So, there are two dereference operators in that expression, meaning that intMatrix is an array of arrays (it contains pointers to pointers).
On the other hand, intMatrix2[(i * lines)+j] is equivalent to *(intMatrix2 + ((i * lines) + j) * sizeof(int)), which contains only one dereference operator. What you're doing here is defining a one-dimensional array that contains the same number of elements as the original two-dimensional array. If your data can be best represented by a matrix, then I recommend you use the first version: intMatrix1[i][j].
The difference is that the first array:
intMatrix1 = (int **)malloc(lines * sizeof(int *));
Creates an array of pointers intMatrix1. Each of those pointers points to an int array (which you malloc here).
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
That's why you need the 2 stars (dereference to the pointer array, then to the int array) in the declaration and the double brackets to access single elements:
int **intMatrix1;
int i = intMatrix[row][column];
int i = *(*(intmatrix + row) + column);
For the second matrix, you create just an int array of size column * rows.
int *intMatrix2 = (int *)malloc(lines * columns * sizeof(int));
int i = intMatrix[row + column];
int i = *(intMatrix + row + column);
To print the 2 arrays you will have to use different print functions, because the internal structure of the 2 matrix is different, but you already know the different methods to access both arrays.
I would like to store values read from a for-loop to an array
char A[];
int x;
int y=5;
for( int i=0; int i =1000; i++) {
x = x+y;
// then store/append x as elements of the char array, A.... what is the syntax?
}
By looking at your code I am assuming that you are trying to build a static array, so I will demonstrate that (so you don't have to focus on concepts like malloc for the time being). There is however, several problems with your code that I will go over now.
First off your array declaration:
char A[];
to me it looks like your for loop is filling an array of integers, so this array should be declared as an integer, furthermore you are not setting the size of the array, since your code has i increment until it is 1000 you should just declare an integer array with 1000 elements:
int A[1000];
Second your for loop:
for(int i = 0, int i = 1000; i++)
you're better off just declaring i with the rest of your variables, although you can declare it in a for loop I personally wouldn't suggest doing it. Also you declare i twice in this loop. Finally your condition to continue the loop (i = 1000) will abort the loop immediatly since i will never be equal to 1000 since you set it to 0. Remember a for loop only loops while the middle statement is true. So with that in mind you should now have:
int A[1000], i, x, y = 5;
for(i = 0; i < 1000; i++)
And now we can use the = statement and the value of i to set each array element for A:
int A[1000], i, x, y = 5;
for(i = 0; i < 1000; i++)
{
x += y;
A[i] = x;
}
it's that simple!
There are multiple issues with your code
char A[1000]; // Need to specify a compile time constant for the array size
int x=0;
int y=5;
for( int i=0; i < 1000; i++) { // Condition was wrong
x = x+y;
// then store/append x as elements of the char array, A.... what is the syntax?
A[i] = x; // Add the value
}
Also, the char datatype won't be able to hold values over a certain size, and will cause overflow making the values wrap around. You might want to declare A as int A[1000] instead.
Arrays need to be of a constant size, or you will need to allocate them using malloc
The second part of the loop cannot redeclare i again. It also will loop forever if you have an assignment statement in it like you do. I assume you want to loop up to 1000 instead
The actual question, to assign into an array use the [] operator.
x was not initialized to anything, making it contain a garbage value. You need to assign values to variables upon declaring them. C does not do this for you automatically.
If you want to add an element in C, you have several methods.
Static array
A static array is declared with a number of elements you're unable to edit. So it's perfect if you know exactly the number of elements you'll have. #Dervall did explain that well.
Dynamic array
A dynamic array is declared with malloc function. And the size can be changed. It's difficult and hard to maintain though. But :
int *A = NULL;
int *tmp; // to free ex allocated arrays
int i;
int j;
int x = 0;
int y = 5;
for (i = 0 ; i < 1000 ; i++) {
// saving temporarly the ex array
tmp = A;
// we allocate a new array
if ((A = malloc(sizeof(int) * (i + 1))) == NULL) {
return EXIT_FAILURE;
}
// we fill the new array allocated with ex values which are in tmp
for (j = 0; j < i; j++) {
A[j] = tmp[j];
}
// if it's not the first time, we free the ex array
if (tmp != NULL)
free(tmp);
x = x + y;
A[i] = x;
}
Better to split it into a function of course :)
You can use the realloc function as well ! Which is made for that, but I find it interesting to develop like this
There's a lot of stuff wrong with your snippet. Here's a compilable example
char *A = malloc(sizeof(*A) * NUM_ELEMENTS); // you shouldn't declare on the stack
int x = 0; // initialize
int y=5;
for( int i = 0; i < NUM_ELEMENTS; i++) { // proper for loop syntax
x = x+y;
A[i]=x; // assign element of array
}
And a better version:
char *A = malloc(sizeof(*A) * NUM_ELEMENTS);
for (int i = 0; i < NUM_ELEMENTS; ++i)
A[i] = 5 * i;
I currently have code for a subroutine to return a pointer to an array. This array is a list of random numbers for a one dimensional monte-carlo integral. I am now trying to do a multi dimensional equivalent which requires 3 arrays of random numbers and instead of having a separate subroutine for each I'm trying to make one which returns a 3 by N + 1 array. Could somebody please help me with the coding for this. A mate mentioned I would need a double pointer but most web sources have been unhelpful thus far. Here is my single array code:
double* rdm_Y(void)
{
double* Random_number_list_Y = calloc(N + 1, sizeof(double));
int i;
sleep(1);
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_Y[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_Y;
}
Many Thanks!
Jack Medley
The general pattern for dynamically allocating a 2D array of type T (where T can be int, double, etc.) is
#include <stdlib.h>
T **alloc(size_t rows, size_t columns)
{
T **arr = malloc(sizeof *arr, rows); // type of *arr is T *
if (arr)
{
size_t i;
for (i = 0; i < rows; i++)
{
arr[i] = malloc(sizeof *arr[i], columns); // type of *arr[i] is T
if (arr[i])
{
size_t j;
for (j = 0; j < columns; j++)
{
arr[i][j] = initial_value_for_this_element;
}
}
}
}
return arr;
}
Try:
struct res{
double *arr1, *arr2, *arr3;
};
main(){
struct res r;
r.arr1 = rdm_Y();
r.arr2 = rdm_Y();
r.arr3 = rdm_Y();
// in r you have 3 pointers to 3 separate arrays
}
or something like this
The three methods I can think of are:
A *double to a 1D array of size 3xN (you can just pretend it's three arrays)
A **double to an array of three *doubles, each one pointing to an array of N
A struct containing three *doubles, each one pointing to an array of N
If you don't like pretending for method 1 you can declare two more *doubles and set them to the return value + N and + 2N respectively. Also don't forget to free() you should have 1, 4, and 3 free()s to do for each of the methods respectively.
I have an array declared as a member of a struct in C. The array is declared as:
char mValue[MAXROWS][MAXCOLUMNS];
where MAXROWS and MAXROWS are 300. Is there a better way to do this? I mean, should I declare these as pointers instead?
Thanks!
As the previous poster suggested, a good way is to create a linear array and then "convert it to 2D". Many times, caching the 2D pointers greatly increases the speed of programs that use this array, like so:
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 a 2D element with:
p2[row][column] = foo;
If all your rows are the same size, you should use a 1D array with the rows stored in sequence:
ABCDE
FGHIJ ---> ABCDEFGHIJKLMNO
KLMNO
The element at row i, column j will be at index i * ROW_LENGTH + j in the 1D array.
You can allocate the array using malloc(ROW_LENGTH * NUM_ROWS).
Another technique 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);
I find that, for this kind of code, its better to create helper functions for accessing the elements. Depending on your profiling data, it may make sense to turn these into macros, but be extra 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's 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;
}
If the array needs to have a dynamic size, then you either need to make it a pointer or make the array the last member of the struct and play games when allocating the structure size.
Relevant comp.lang.c FAQ entries:
I came across some code that declared a structure like this...
How can I dynamically allocate a multidimensional array?
I found that changing my approach was very useful when faced with a similar problem.
A vector of vectors filled the same task, avoided memory allocation obstacles, and kept the same familiar shorthand. There may be other pitfalls, but I have not encountered 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's b-th element
If you are struggling with arrays, but strongly desire the familiar indexing language, I have found this to be a good alternative.
Note that indexing order A then B is going to be critical for memory usage when recalling this data. Failure to call the information in an A,B order will be deeply problematic if performance is an issue.