I am trying to return a modern 2D dynamic array after allocating memory to it and filling it up with character values. I tried working around some errors but ultimately got stuck at a dead end. I originally had a working 2D dynamic array implementation return in functions using array-of-pointers method from C90 but I am told that has overhead and is out-of-date. So, I decided to try and upgrade using modern C 2D array approach taken from here: How do I work with dynamic multi-dimensional arrays in C?.
Alas, it ended up not working in my implementation so I am now wondering what I may have done wrong. Please see my below code for full reference: (Goal was to make a 2D matrix of a checkerboard within helper functions to main)
char **allocateToBoardC99(const int nthDim)
{
char(*boardArray)[nthDim] = malloc(sizeof(char[nthDim][nthDim]));
return (char **)boardArray;
}
char **getCheckeredBoardC99(const int nthDim)
{
bool startWithWhiteTile = true;
// C99 version (more elegant):
char **arr = allocateToBoardC99(nthDim);
// Make the board checkered by alternating char assignments based on a bool latch
for (int rowIndex = 0; rowIndex < nthDim; rowIndex++)
{
if (startWithWhiteTile)
{
for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
{
arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'W' : 'B';
}
startWithWhiteTile = false;
}
else
{
for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
{
arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'B' : 'W';
}
startWithWhiteTile = true;
}
}
return (char **)arr;
}
int main(int argc, char *argv[])
{
// Initialize dimension of the checker board:
int dim = 8;
// char **boardMatrix = getCheckeredBoardC90(dim); // Works
char **boardMatrix = getCheckeredBoardC99(dim);
printf("hello world");
printf("\n");
for (int row = 0; row < dim; row++)
{
printf("[");
for (int column = 0; column < dim; column++)
{
printf("%c ", boardMatrix[row][column]);
}
printf("]\n");
}
return 0;
}
If you're curious about the above getCheckeredBoardC90(dim);
working, here is the following sequence of code that made it work (while the newer C99 doesn't):
char **allocateToBoardC90(const int nthDim)
{
// The calloc() function reserves storage space for an array of NUM elements, each of length SIZE bytes:
// calloc(size_t NUM, size_t SIZE)
char *values = calloc(nthDim * nthDim, sizeof(char)); // In our 2D board array, we would have nxn (char)elements (8x8=64 elements)
// Simple way is to allocate a memory block of size row and access its elements using simple pointer arithmetic:
char **rows = malloc(nthDim * sizeof(char)); // pointer to overall space
// Iterate through each *row; 0 to nthRow
for (int rowIndex = 0; rowIndex < nthDim; rowIndex++)
{
rows[rowIndex] = values + (rowIndex * nthDim);
}
// Returns an array of pointers (array of arrays)
return rows;
}
char **getCheckeredBoardC90(const int nthDim)
{
bool startWithWhiteTile = true;
//**array[rowIndex][columnIndex]
// char **arr[nthDim][nthDim];
// C90 version (lotta pointers; be aware of performance overhead):
char **arr = allocateToBoardC90(nthDim);
// Make the board checkered by alternating char assignments based on a bool latch
for (int rowIndex = 0; rowIndex < nthDim; rowIndex++)
{
if (startWithWhiteTile)
{
for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
{
arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'W' : 'B';
}
startWithWhiteTile = false;
}
else
{
for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
{
arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'B' : 'W';
}
startWithWhiteTile = true;
}
}
return arr;
}
int main(int argc, char *argv[])
{
// Initialize dimension of the checker board:
int dim = 8;
char **boardMatrix = getCheckeredBoardC90(dim); // Works
// char **boardMatrix = getCheckeredBoardC99(dim);
printf("hello world");
printf("\n");
for (int row = 0; row < dim; row++)
{
printf("[");
for (int column = 0; column < dim; column++)
{
printf("%c ", boardMatrix[row][column]);
}
printf("]\n");
}
return 0;
}
If the helper functions return correctly, then main's output should look something like this:
hello world
[W B W B W B W B ]
[B W B W B W B W ]
[W B W B W B W B ]
[B W B W B W B W ]
[W B W B W B W B ]
[B W B W B W B W ]
[W B W B W B W B ]
[B W B W B W B W ]
Specific help on this would be greatly appreciated, thank you!
NOTE: Originally with this dynamic 2D array modern C code, I was trying to return the 2D array from an allocator function (really a reference to it), pass that 2D array's reference to an element-initializer function to fill up the checkerboard like usual, and then finally pass the finalized 2D array (as a reference) to the main function to check the contents of the 2D array through terminal output.
What ended up happening was a lot of trial and error to resolve pointer-to-object issues, pointer casting, etc. This only led (from what I believe is improper C-pointer casting) to an end-game "Segmentation Fault" in the getCheckeredBoardC99
function.