1
typedef struct nestedStruct
{
    int a;
    int b;
    char* name;
} nestedStruct;

typedef myStruct
{
    int count;
    nestedStruct myNestedStruct[];
}

I need to define flexible structure which would have number of nested structures in it and structures themselves. And then I need to explicitly initialize them like

myStruct realStruct
{
    2,
    { 1, 2, "name 1" },
    { 3, 4, "name 2" }
} realStruct;

There will be a number of applications using the structure at the width they need.

It is clear for me that this syntax is not correct, I can't find the right one, and this explicitly states it is not possible. Why?

Any suggestions how I can make a "bus" of data structures without separating them into number of pointers to be able to pass single pointer to such struct to the functions and these functions knowing the layout of these bus without additional parameters.

Edit:

this one works

myStruct realStruct
{
    2,
    {
        { 1, 2, "name 1" },
        { 3, 4, "name 2" }
    }
} realStruct;

but there's pedantic warning

warning: initialization of a flexible array member [-Wpedantic]

Well, warnings are there to let me know I may do something incorrectly. Is there a way to tell compiler this is what I actually want to do - without suppressing the warning at all?

Solution:

not that elegant I wanted to, but: replace array with the pointer to array.

typedef myStruct
{
    int count;
    nestedStruct* myNestedStruct;
} myStruct

nestedStruct myList[] =
{
    { 1, 2, "name 1" },
    { 3, 4, "name 2" }
}

myStruct realStruct
{
    2,
    myList
} realStruct;

10
  • 2
    You might want to look at this stackoverflow.com/questions/8687671/… Flexible array member needs explicit allocation before it can be assigned. Commented Feb 14, 2024 at 16:48
  • Have seen this, but it says rather how to do it differently than why it is not possible. And there's no sense to touch memory heap for objects with known size at the compile time. Hmmm however I initialize object, not define it... Commented Feb 14, 2024 at 16:51
  • 1
    Instead of rewriting what you've tried from memory, copy the real thing into the question so that not everyone else has to correct your mistakes. Commented Feb 14, 2024 at 16:53
  • It is not necessarily to allocate on heap. You can do tricks with static allocation too, for example by making it a part of union with some sufficiently large byte array. OTOH If as you say, the size is known in compile time, then why not make it fixed size array instead? Commented Feb 14, 2024 at 16:55
  • @EugeneSh. for one application size will be 2, for another may be 10, but layout will be the same - number of members, some other properties for the group, and members themselves in very specific struct format. I was hoping I can make a template for such a thing. Commented Feb 14, 2024 at 16:58

1 Answer 1

0

Flexible array members were invented for dynamic memory allocation.

typedef struct nestedStruct
{
    int a;
    int b;
    char* name;
} nestedStruct;

typedef struct myStruct
{
    size_t count;
    nestedStruct myNestedStruct[];
}myStruct;



myStruct *init(void)
{
    myStruct *str = malloc(sizeof(*str) + 2 * sizeof(str -> myNestedStruct[0]));
    if(str)
    {
        str -> count = 2;
        str -> myNestedStruct[0] = (nestedStruct){ 1, 2, "name 1" };
        str -> myNestedStruct[1] = (nestedStruct){ 3, 4, "name 2" };
    }
    return str;
}

myStruct *init1(size_t size, nestedStruct *initData)
{
    myStruct *str = malloc(sizeof(*str) + size * sizeof(str -> myNestedStruct[0]));
    if(str)
    {
        str -> count = size;
        memcpy(str -> myNestedStruct, initData, size * sizeof(*initData));
    }
    return str;
}

myStruct *add(myStruct *str, nestedStruct *data)
{
    size_t newsize = str ? str -> count + 1 : 1;
    str = realloc(str, sizeof(*str) + newsize * sizeof(str -> myNestedStruct[0]));
    if(str)
    {
        str -> count = newsize;
        str -> myNestedStruct[newsize - 1] = *data;
    }
    return str;
}


int main(void)
{
    myStruct *s1 = init();
    myStruct *s2 = init1(2, (nestedStruct[]){{ 1, 2, "name 1" },{ 3, 4, "name 2" }});

    myStruct *s3 = add(NULL, (nestedStruct[]){{ 1, 2, "name 1" }});
    /* yuo should check if those functions did not return NULL */
    myStruct *tmp = add(s3, &(nestedStruct){ 3, 4, "name 2" });
    if(tmp) s3 = tmp;

    free(s1);
    free(s2);
    free(s3);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.