In my current project, which uses the MISRA 2004 standard, we use three GCC compilers, versions 3.2.3, 4.4.2 and 5.4.0.
We run build checks with the pedantic switch and c89 standard and a load of other restrictions. One of the restrictions is that all data must be initialised at declaration.
I have a problem in that on GCC 3.2.3, the universal zero initialiser {0}
only compiles for arrays of the basic unitary types. If I have an array of structs, then I get a missing braces warning and the warning only goes away if I change {0}
for {{0}}
.
struct my_type my_thing[NUMBER_OF_THINGS] = {0};
becomes
struct my_type my_thing[NUMBER_OF_THINGS] = {{0}};
This does not work, however, for arrays of structs which have struct members. Then the problem is with the 4.4.2 compiler, which gives missing initialiser errors, so I had to do this:
struct my_struct_with_structs_inside my_other_thing[NUMBER_OF_THINGS] = {{0, 0, {0}, 0}};
This satisfies the compilers, but it trips our MISRA checker, because MISRA demands either the universal single {0} initialiser or the full, whole-array initialiser:
struct my_struct_with_structs_inside my_other_thing[NUMBER_OF_THINGS] = {{0, 0, {0}, 0}, {0, 0, {0}, 0}, {0, 0, {0}, 0}, {0, 0, {0}, 0}, {0, 0, {0}, 0}};
This is impractical for us because we have all sorts of restrictions and NUMBER_OF_THINGS
may be changeable and be automatically generated from outside the source code at build time.
I would like to be able to say to my boss that the so-called universal initialiser {0}
is sufficient for initialising any array. I have found threads on the GCC mailing lists and Bugzilla, going back many years, which consider the compiler warnings I've mentioned to be bugs, and stating that {0}
is part of the standard. However, none of them mention which standard, and I have been unable to find {0}
in the ISO C89 or C99 drafts, or K&R v2. Is the {0}
a standard? Is there any way to guarantee that an array of structs with struct members is initialised to all zeros (or NULL)?
The trouble is that, while I can magic away the violations of the MISRA code, I am unsure that doing this:
struct my_struct_with_structs_inside my_other_thing[NUMBER_OF_THINGS] = {{0, 0, {0}, 0}};
...is sufficient to guarantee that the array will be completely zeroed.
Can anyone please offer wisdom from the root of this problem?
std::array::array For elements of a class type this means that their default constructor is called. For elements of fundamental types, they are left uninitialized (unless the array object has static storage, in which case they are zero-initialized).
Zero Initialization in C++Setting the initial value of an object to zero is called the zero initialization. Zero is initialized for every named variable with static or thread-local storage duration that is not subject to constant initialization (since C++14), before any other initialization.
The array will be initialized to 0 if we provide the empty initializer list or just specify 0 in the initializer list.
Implicitly defined (by the compiler) default constructor of a class does not initialize members of built-in types.
The {0}
initializer to initialize all objects in an aggregate (meaning array or struct) is 100% standard in any version of C. The syntax allows you to omit the braces for sub-aggregates.
I won't go into all the dirty details here. In case you are interested in the formal normative text, this is explained in a number of intricate rules that you can read about in for example C11 6.7.9 from §17 and forward.
Regarding MISRA-C:2004, this rule was a bit cumbersome and there is a MISRA-C:2004 TC1 regarding it. Your static analyser might not properly implement TC1 9.2 which stated that {0}
on the top level is compliant.
Still, the TC1 didn't quite sort all things out. I asked the committee about this back in 2008 here:
https://www.misra.org.uk/forum/viewtopic.php?f=65&t=750
The reply I got there is a formal committee response and may be used as reference in your documentation. The committee agreed that the rule needed further improvement and based on this the rule was fixed in MISRA-C:2012 where {0}
may be used anywhere to initialize subobjects of aggregate type.
I would recommend to use MISRA-C:2012 if possible.
Yes. {0}
is valid universal initializer in C89, too:
If there are fewer initializers in a list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
It's true in all newer versions of the standard as well.
The warning you get from gcc is an old bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80454 which was fixed around gcc 4.9.
For your situation, you could consider:
-Wno-missing-braces
option to silence the warning since this is a known bugmemset
to initialize your struct typesIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With