2

This sketch does not compile in the Arduino IDE

void setup() {
  // put your setup code here, to run once:

}

struct test {
  int i;
  char variable[];
};

typedef struct test test;

test t = {
  0, "hi"
};

void loop() {
  // put your main code here, to run repeatedly:

}

Arduino throws

sketch_may09a:16: error: initializer-string for array of chars is too long [-fpermissive]

 };

 ^

exit status 1
initializer-string for array of chars is too long [-fpermissive]

However compiling with g++ works just fine. How can I fix it? Or is there a principle reason why flexible array members are not supported?

4
  • 1
    It hurts to see that code, so it must be wrong. A struct is a definition of a variable (wich contains other variables). How would you create an array of those structs when they have different lengths?
    – Jot
    May 9, 2019 at 20:02
  • @Jot: The struct type itself is declared correctly. There's nothing wrong with an [] array as the last member of a struct. However, in standard C language the only way to make such structs to "have different lengths" is to malloc them individually. This is what this [] feature is designed for. In all other contexts the [] array simply "disappears" (i.e. it is an array of size 0). So, the issue simply does not exist in situations when one'd try to create an array of such structs. May 9, 2019 at 20:18
  • @AnT I know that it is set to zero size and I have read your answer with the correct type definition and declaration of the structs. the_architect tries to put the characters into the struct itself. That is not possible.
    – Jot
    May 9, 2019 at 20:50
  • @Jot Not sure what answer you are talking about. Placing the characters into the struct itself, as the OP is trying to, is possible through GNU-specific extension. As I said already, the OP code is perfectly correct from GNU point of view. May 9, 2019 at 20:55

2 Answers 2

5

Flexible array member is a C feature. It does not exist in C++. On top of that, the way you use it to declare and initialize a static struct of flexible size is non-standard even for C.

However, GNU-C language supports it as an extension. Also, newer versions of GCC (6 and higher) allow this in GNU-C++ code as an extension as well. But GCC 5.4.0 used by Arduino IDE doesn't support this non-standard feature in C++ code.

If you flip through different GCC versions on Godbolt (https://godbolt.org/z/Iul7hD) you'll see that support for this feature has always been present in C code, but for C++ code it first appeared in GCC 6.

This is why you were able to compile it with your standalone g++ compiler (which is apparently a much later version), but were unable to compile it in Arduino IDE.

It means that if you really want this non-standard code to compile in the current version of Arduino IDE, you have to place it into a .c file. Or just specify the array size explicitly.

2
  • Thanks for the link to godbolt. I tried a few things and it goes wrong very fast. For example adding a variable to the struct after the flexible array, or with an array of structs. Some things work with gcc version 6, but not with 8 or 9. The sizeof() does not include the flexible array member. And so on.
    – Jot
    May 11, 2019 at 1:13
  • 1
    @Jot: Flexible array member is naturally supposed to be the last field of the struct. Yes, sizeof does not take it into account. Flexible array members are intended to provide support for the good old "struct hack" (c-faq.com/struct/structhack.html) and the fact that sizeof ignores this member makes it easier to calculate the proper size for malloc. May 11, 2019 at 1:26
2

Maybe you've compiled it in g++ without any warnings enabled (or maybe it yeld warnings but was compiled). The arduino uses flags to consider all warnings as an error, so it won't compile. It may wary for different platforms, I've got -fpermissive used (and I don't like it at all).

That's because size of struct must be known compile time and if you provide char variable[]; you'll get zero sized array. Therefore anything biiger than nothing you'll try to initialize for is too long.

Maybe you're looking for something like this:

struct test {
  int a;  
  const char * ptr;
};

test paramx {1, "some string"};
test paramy {2, "another string"};

test array[] = {{3,"three"}, {4, "four"}, {5,"five"}};
7
  • char variable[]; is not a zero-sized array. It is a flexible array. In standard C its size depends on how much memory was allocated by the user for the whole struct object. And in extended GNU-C the extra memory can be requested the way the OP requests it: by using an {} initializer. As far as GNU-C is concerned, the code is perfectly fine. May 9, 2019 at 20:13
  • 1
    And it works like it's zero size array pointing after the end of struct, so you have to allocate more than sizeof(struct) to use it without "buffer overflow". But as it was noted, it can't work on statically allocated struct instance. And in C++ it has to be struct containing POD's only.
    – KIIV
    May 9, 2019 at 20:17
  • Well, it can't work for non-dynamic struct object in pedantic standard C. But the OP is apparently not trying to use pedantic standard C. And yes, it can and will work in extended GNU-C (and in GNU-C++ after version 6 of the compiler). The original code is perfectly fine as far as GNU-extended versions of these languages are concerned. The code will compile and work as intended in Arduino IDE once it is placed into a .c file, as I clearly stated in my answer. Once Arduino IDE moves to a later version of AVR-GCC, this code will compile and work as intended right away. May 9, 2019 at 20:21
  • Hower I'm not sure he really wanted to use FAM. It might be just coincidence. Maybe he wanted just const char * variable; That should be perfectly legal in this case (or flash string helpers / progmem pointers)
    – KIIV
    May 9, 2019 at 20:30
  • The title of the question seems to suggest that the OP did actually want to use a variable-size struct. Whether they meant it literally, as a reference to this specific language feature - I don't know. May 9, 2019 at 21:01

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.