typedef struct RGB {
unsigned char red;
unsigned char green;
unsigned char blue;
} RGB;
typedef struct canvas {
int width;
int height;
RGB **data;
} canvas;
RGB WHITE = { 255, 255, 255 };
canvas mkcanvas (int width, int height)
{
canvas c;
c.width = width; c.height = height;
RGB a[width][height];
int i = 0, j = 0;
for (; i < width; i++)
for (; j < height; j++)
a[i][j] = WHITE;
c.data = (RGB **)a;
return c;
}
In mkcanvas, how do turn c.data into a two dimensional array. I've tried some silly mallocs and the above but it doesn't work. It segfaults when trying to access c.data[0][0].red.
Never mind this, the guys at ##c tell me it isn't really possible.
The segfault is because both the canvas and the RGB array are allocated on the stack, so disappear as soon as the function returns. Any use of them after they go out of scope will have unexpected results, and is most certainly a bug.
To make a two dimensional array? Make a one dimensional array of pointers to one dimensional arrays.
In C, the easiest way to get good results would be a function that constructs and allocates the structure, or returns NULL if it fails.
(Warning: Barely tested, and only theoretically bug-free)
(Almost certainly needs to be modified to use the same brace style and indentation as the rest of the code, and the iterator declarations might need to be moved too. If they do, then keep the row = 0 and col = 0 in the for loops, otherwise it won't work (specifically, only the first row and last column would be initialized if the col loop didn't have col = 0, and having the row = 0 is just for consistency))
canvas* newCanvas(int width, int height, RGB initialColour)
{
if(width <= 0 || height <= 0)
return NULL;
canvas *c = malloc(sizeof(canvas));
if(c == NULL)
return NULL;
c->width = width;
c->height = height;
c->data = malloc(sizeof(RGB*) * height);
if(c->data == NULL)
{
free(c);
return NULL;
}
for(int row = 0; row < height; row++)
{
c->data[row] = malloc(sizeof(RGB) * width);
if(c->data[row] == NULL)
{
while(row--)
free(c->data[row]);
free(c->data);
free(c);
return NULL;
}
for(int col = 0; col < width; col++)
c->data[row][col] = initialColour;
}
return c;
}
Edit: A one-dimensional array where you manually convert [
x][y] into [(y*width) + x] would also work.