This is an old topic:


But some points were left not covered.

  1. “code hygiene” I’d say is that, the code should

just be portable to “all” compilers, and have the same meaning

with all of them, with a minimum of ifdefs.

  1. Furthermore, regarding “same meaning” to all of them,

there are these choices:

typedef struct A1 {

int a;

int b[0];

} A1;

typedef struct A2 {

int a;

int b[];

} A2;

typedef struct A3 {

int a;

int b[1];

} A3;

int a1 = sizeof(A1);

int a2 = sizeof(A2);

int a3 = sizeof(A3);

They are all valid with clang and probably gcc.

But they are not likely all valid with additional compilers and through time.

[1] seems like the most portable and oldest form, and might as well just keep using it indefinitely.

But it gets a warning.
If one were to ifdef clang to avoid it, one would lose interopation across compilers, as
the various forms do not have the same meaning.
Everyone would have to compile with the same compiler/defines.

Else the types would vary in size.

So I come back to believing that the best choices are either:

  • do not warn for size=1 at end of aggregate

  • possibly a separate setting for specifically that

That is what gcc does also it appears (both).

I ran across all this exact situation – ifdef gnuc/clang in some code, with comment that everyone has to compile the same, chosing between 0 and 1 for zero sized array.

Thank you,

  • Jay

Supporting the oldest form doesn’t seem to be a priority for a warning - if you have a very old codebase, probably not worth building it with warnings enabled. Updating code to use more modern/idiomatic forms is within scope for Clang’s warnings, within reason, I think.

  • Dave