Yunus King
Yunus King

Reputation: 1271

C99 designator member outside of aggregate initializer

struct Foo {
    char a[10];
    int b;
};

static Foo foo = {.a="bla"};

Compiling the above code gives the following gcc error:

$ gcc -std=gnu++2a test.cpp 

C99 designator ‘a’ outside aggregate initializer

I thought that c-string designators in initializer list like these are ok in C++20? What am I missing? I am using gcc version 10.

Upvotes: 12

Views: 9850

Answers (4)

Chris Newman
Chris Newman

Reputation: 1

Another option that worked for me is to include the extra NULL characters, for a total of size-1, since one NULL is automatic, for example:

struct Foo {
    char a[6];
    int b;
};

static constexpr Foo foo = {.a="bla\0\0"};

Upvotes: 0

Artyer
Artyer

Reputation: 40891

This is a known bug with GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55227

Unfortunately, you will have to either not use designated initializers or use a different initializer for the array:

static Foo foo = {"bla"};
static Foo foo = {.a={'b', 'l', 'a', 0}};

// Or if you can change Foo:
struct Foo {
    std::array<char, 10> a;
    int b;
};
static Foo foo = {.a={"bla"}};

This appears to have been fixed in GCC 11.3 if you can upgrade your compiler.

Upvotes: 22

AgainPsychoX
AgainPsychoX

Reputation: 1801

I use strncpy (from <cstring>), for example:

strncpy(foo.str, "hello", sizeof(foo_t::str));

It seems to be optimized away, therefore generating the same assembly as normal approach in newer GCC (11.3^) and the same as using Artyer solution (the accepted one) of using char array.

Godbolt link: https://godbolt.org/z/9G7b6PT9b

However, the solution might cause warning: missing initializer for member 'foo_t::str' [-Wmissing-field-initializers] if you have the -Wextra warnings enable, but you can use -Wno-missing-field-initializers to exclude it.

By the way, with stucts like that you always have to remember the space is limited, and in many cases you might want leave trailing zero for string end. Using strncpy you can force that by adding:

foo.str[sizeof(foo_t::str) - 1] = 0;

Upvotes: 0

linmin shan
linmin shan

Reputation: 11

I got the same error and I dealt with mv my.cpp my.c

You also can find answer in this link: https://pcbartists.com/firmware/esp32-firmware/designator-outside-aggregate-initializer-solved/

#ifdef __cplusplus
extern "C"
{
#endif

    // C code goes here
    
#ifdef __cplusplus
}
#endif

Upvotes: 1

Related Questions