Home > Enterprise >  Initialize an array of structs containing dynamic arrays
Initialize an array of structs containing dynamic arrays

Time:12-03

I am trying to create a table of elements (structs) where each element contains a dynamic list of enums in C. However, it seems this is not possible in C as I keep getting the following error:

error: initialization of flexible array member in a nested context

Here is a small sample of my code:

#include <stdio.h>
#include <stdint.h>

typedef enum {
    NET_0   = 0,
    NET_1,
    NET_2,
    TOTAL_NETS,
} net_t;

typedef struct {
    uint8_t num_nets;
    net_t net_list[];
} sig_to_net_t;

sig_to_net_t SIG_NET_MAPPING[] = {
    {1, {NET_0}},
    {2, {NET_1, NET_2}},
    {1, {NET_2}},
};

Any solution for this issue in C?

FYI, the only solution I found would be to replace the dynamic array net_list with a fixed-size array. However, this solution is not optimal as this code will be flashed on memory-limited devices and I have cases where the net_list will contain 5 elements which are only a few cases out of 1000 entries in the SIG_NET_MAPPING table.

CodePudding user response:

You can use pointer to array of enums:

typedef enum {
    NET_0   = 0,
    NET_1,
    NET_2,
    TOTAL_NETS,
} net_t;

typedef struct {
    uint8_t num_nets;
    net_t *net_list;
} sig_to_net_t;

sig_to_net_t SIG_NET_MAPPING[] = {
    {.num_nets = 1, .net_list = (net_t[]){NET_0}},
    {.num_nets = 2, .net_list = (net_t[]){NET_1, NET_2}},
};

https://godbolt.org/z/EMz9qqeYc

If you want to have in FLASH in embedded system add some consts

typedef struct {
    uint8_t num_nets;
    const net_t *const net_list;
} sig_to_net_t;

const sig_to_net_t SIG_NET_MAPPING[] = {
    {.num_nets = 1, .net_list = (const net_t[]){NET_0}},
    {.num_nets = 2, .net_list = (const net_t[]){NET_1, NET_2}},
};

CodePudding user response:

Using a fixed size array is your only option.

A struct with a flexible array member is not allowed to be a member of an array (or another struct). One reason for this is that there's no way to know exactly where one array element ends and another one starts if each one could have a different size.

One way you can manage the size is to either change the type of the net_list member to char or use a compiler option like gcc's -fshort-enums to make the enum type only take up one byte.

CodePudding user response:

To add to 0___________'s answer; you can use macros to make sure num_nets is correct:

https://godbolt.org/z/8PE617YbT

/* gcc -Wno-incompatible-pointer-types .\multisize_array.c -o .\multisize_array.exe */

#include <stdio.h>
#include <stdbool.h>

#include <stdio.h>
#include <stdint.h>

typedef enum {
    NET_0   = 0,
    NET_1,
    NET_2,
    TOTAL_NETS,
} net_t;

typedef struct {
    uint8_t num_nets;
    net_t * net_list;
} sig_to_net_t;

#define array_size(ARR) (sizeof(ARR)/sizeof(ARR[0]))

#define NET_MAPPING(...) { \
    .num_nets = array_size(((net_t[]){__VA_ARGS__})), \
    .net_list = (net_t[]){__VA_ARGS__} \
}

sig_to_net_t SIG_NET_MAPPING[] = {
    NET_MAPPING(NET_0),
    NET_MAPPING(NET_1, NET_2),
    NET_MAPPING(NET_1, NET_2),
    NET_MAPPING(NET_2, NET_2, NET_2, NET_2, NET_2, NET_2, NET_2, NET_2),
};

#define array_size(ARR) (sizeof(ARR)/sizeof(ARR[0]))

int main(void)
{
    int ret = 0;
    for (int i = 0 ; i < array_size(SIG_NET_MAPPING) ; i   ) {
        const sig_to_net_t * const pStn = &SIG_NET_MAPPING[i];
        printf("{");
        const char * sep = "";
        for (int ii = 0 ; ii < pStn->num_nets ; ii   ) {
          printf("%s%d", sep, pStn->net_list[ii]);
          sep = ", ";
        }
        printf("}\n");
    }
    return ret;
}
  • Related