The title corresponds to my last attempt, I try to store color values corresponding to walls, a bit like this:
#include <stdint.h>
typedef uint8_t RGB[3];
typedef RGB ColorArray[];
typedef struct {
int wall_num;
ColorArray wall_colors;
} Map;
int main(void)
{
int wall_num = 3;
ColorArray wall_colors = {
*(RGB){ 255, 0, 0 },
*(RGB){ 0, 255, 0 },
*(RGB){ 0, 0, 255 }
};
Map my_map = {wall_num, wall_colors}; // error: non-static initialization of a flexible array member
return 0;
}
But I get this:
error: non-static initialization of a flexible array member
I tried other ways with pointers but I quickly realized that it was pointing to anything and so I got any colors until a segfault...
Is there a way to do it like this ? Or is it just the wrong way to go and I have to start all over again ?
UPDATE - (SELF ANSWER):
So I decided to call malloc() because no alternative was satisfactory for my case, I share what I did if it can help someone:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef uint8_t RGB[3];
typedef RGB RGB_Array[];
typedef struct {
int wall_num;
RGB_Array wall_colors;
} Map;
void print_map (Map *m) {
printf("wall_num: %d\n", m->wall_num);
for (int i = 0; i < m->wall_num; i) {
printf("wall_colors[%d]: (R:%d, G:%d, B:%d)\n", i,
m->wall_colors[i][0],
m->wall_colors[i][1],
m->wall_colors[i][2]);
}
}
int main(void)
{
int wall_num = 3;
RGB_Array color_arr = {
{255,0,0},
{0,255,0},
{0,0,255}
};
Map* map = malloc(sizeof(Map) sizeof(color_arr));
map->wall_num = wall_num;
memcpy(map->wall_colors, color_arr, sizeof(color_arr));
print_map(map);
free(map); // free is for example
return 0;
}
Otherwise, jxh's answer is still interesting and perfectly does what was asked for, even if it doesn't suit me personally, I validate it anyway.
CodePudding user response:
You cannot use an array name to initialize an array variable anyway.
There is no memory associated with the flexible array member. It is a convenience to allow you to have a name for the end of the struct
to refer to the array that you intend to allocate behind the struct
.
Typically, you would use malloc()
and add the size of the array to the size of the struct
to get a single object to represent your structure with the flexible array.
However, you can do it off the "stack" by defining a new structure where the flexible array member is replaced with an array of the appropriate size, and then casting a pointer to this structure to your desired type.
Alternatively, you could use a union
and avoid the casting.
Both techniques are illustrated below. First some helpers:
...
#define MAP_TEMPLATE(N) struct { \
int wall_num; \
RGB wall_colors[N]; \
}
...
void print_map (Map *m) {
printf("wall_num: %d\n", m->wall_num);
for (int i = 0; i < m->wall_num; i) {
printf("wall_colors[%d]: (R:%d, G:%d, B:%d)\n", i,
m->wall_colors[i][0],
m->wall_colors[i][1],
m->wall_colors[i][2]);
}
}
Then using a new structure:
MAP_TEMPLATE(3) my_map1 = {
wall_num,
{ { 155, 0, 0 },
{ 0, 155, 0 },
{ 0, 0, 155 },
},
};
print_map((Map *)&my_map1);
And using a union:
union {
MAP_TEMPLATE(3) _;
MAP_TEMPLATE();
} my_map2 = {
{ wall_num,
{ { 255, 0, 0 },
{ 0, 255, 0 },
{ 0, 0, 255 },
},
},
};
print_map((Map *)&my_map2);