9

I've a question regarding the following code:

#include "all_needed.h"

static uint8_t array[2] = {0};

void main(void)
{
  ...
}

Is a (module) global array allowed to be initialized as above for having each member set to zero while being ANSI C conform?

I've got a problem in Code Composer 5 (MSP430 Project) where I had to change it into

static uint8_t array[2] = {0, 0};

for a correct initialization of the 2nd member of the array.

Tild
  • 153
  • 1
  • 6
  • 3
    why ask if it conforms when, IIRC, void main is not conforming. – KevinDTimm Nov 15 '11 at 15:24
  • 3
    @KevinDTimm, how do you know that this `main` is not conforming? The standard allows for platform specific signatures of `main` for freestanding environments, the only obligation is for the vendor to document this. Do you know the msp430 platform sufficiently well to make such an assertion? – Jens Gustedt Nov 15 '11 at 15:58
  • 1
    @JensGustedt Note the `IIRC` - my `Remember` will now be modified – KevinDTimm Nov 15 '11 at 17:07
  • 1
    Your compiler appears to be non-conformant, but having it confirmed here is not really much help to you, if that is the only compiler you have, except perhaps to give you confidence when you raise a bug report to TI. You should check the compiler's documentation first, the deviation may be deliberate and documented or in the errata. If you do not have an initialiser at all, I would imagine that it will be correctly initialised to zero in this particular case. – Clifford Nov 15 '11 at 21:47
  • It appears that the compiler is indeed non-conformant. I'll put the solution as an edit into the former question. – Tild Nov 16 '11 at 10:46
  • 1
    @Tild: Don't write answers in questions, please. Move it into an answer. – Lightness Races in Orbit Nov 16 '11 at 11:00
  • Code composer is indeed not compliant, there was some discussion about that on the TI forum. For example (and it is very relevant here), it does not initialize global variables to 0/false/NULL if not explicitly done in the source. This made me choose another compiler. – Gauthier Jan 23 '12 at 09:36

5 Answers5

11

Yes, this is allowed, and should initialize the array to zero. C99, §6.7.8 p10:

If an object that has static storage duration is not initialized explicitly, then:

— if it has pointer type, it is initialized to a null pointer;

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

— if it is an aggregate, every member is initialized (recursively) according to these rules;

— if it is a union, the first named member is initialized (recursively) according to these rules.

and p21:

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

Report the bug to your compiler vendor.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
6

Thanks for all your answers! I've further investigated and found out that the Compiler is non-compliant as described in http://www.ti.com/lit/pdf/SLAU157 in section B.5.1 "Initializing Static and Global Variables":

Appendix B: IAR 2.x/3.x/4.x to CCS C-Migration

B.5 Other Differences

B.5.1 Initializing Static and Global Variables

The ANSI/ISO C standard specifies that static and global (extern) variables without explicit initializations must be pre-initialized to 0 (before the program begins running). This task is typically performed when the program is loaded and is implemented in the IAR compiler:

/* IAR, global variable, initialized to 0 upon program start */
int Counter;

However, the TI CCS compiler does not pre-initialize these variables; therefore, it is up to the application to fulfill this requirement:

/* CCS, global variable, manually zero-initialized */
int Counter = 0;
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
Tild
  • 153
  • 1
  • 6
  • 1
    What an ugly 'difference'. The amount of existing code that assumes that statics/globals are implicitly initialized to 0 must be enormous. Granted, an MSP430 can be very resource limited, but you have to initialize variables somewhere anyway. If they needed to support uninitialized data for some reason, they really should have an explicit way to specify it (like maybe an `__uninitialized` keyword or something - `int Counter = __uninitialized;`). Then you'd have better results using portable code in MSP430 projects. – Michael Burr Nov 10 '12 at 08:06
5

The C standard says (6.7.8.21):

If there are fewer initializers in a brace-enclosed list than there are element of members of an aggregate [...], the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

In 6.2.5.21:

Array and structure types are collectively called aggregate types.

In other words, your code is OK.

Lindydancer
  • 25,428
  • 4
  • 49
  • 68
4
static uint8_t array[2] = {0};

According to the C Standard, this will initialize both members of array to 0. If your compiler doesn't zero them, then it is in violation.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 2
    IIRC, per the standard, isn't the `= {0}` superfluous? – KevinDTimm Nov 15 '11 at 15:22
  • 5
    @KevinDTimm: yes, it is. However, it's no less required that the compiler do the right thing in the presence of a superfluous initializer. – Stephen Canon Nov 15 '11 at 15:23
  • @StephenCanon - Agreed, I've just always enjoyed the freedom of no stated initializer means `initialize to zero` – KevinDTimm Nov 15 '11 at 17:25
  • @KevinDTimm The `= {0}` is superfluous for a whole-program duration variable, but it would be necessary for an automatic variable, which is why some programmers always put an initializer for simplicity's sake. On the other hand, for many compilers, `= {0}` for a whole-program duration causes an initial value for the array to be stored in the program binary and loaded when the program starts, which is why an all-zero initializer is best avoided for large static arrays. – Gilles 'SO- stop being evil' Nov 15 '11 at 22:07
  • @Gilles - aren't all `static` variables `whole program duration`? – KevinDTimm Nov 15 '11 at 22:19
  • @KevinDTimm Yes, I was using the terms synonymously (not all whole-program duration variables have the `static` keyword: anything at file scope or `extern` has whole-program duration). – Gilles 'SO- stop being evil' Nov 15 '11 at 22:21
  • @Gilles - I don't understand your comment about an all-zero initializer being "best avoided". Or perhaps you are calling the "= {0}" form an all-zero initializer? If the compiler treats that whole array then as initialized data, that would increase the executable size, which is what I think you are saying. But using implicit initialization is also all-zero, so I am confused. – David Winant Nov 16 '11 at 15:33
  • @DavidWinant Many compilers implement `={0}` by loading a chunk of data from the executable and implicit initialization by an internal `memset(…,0,…)`. Of course, that's an implementation detail: the semantics at the C level are the same. – Gilles 'SO- stop being evil' Nov 16 '11 at 15:44
0

I work with PIC micros, so your mileage may vary...

There are different startup libraries I can link in. One will not initialize any RAM. One will clear all RAM to 0. Another with initialize the variables normally.

Take a look at the linker file and see what it is doing.

Robert Deml
  • 12,390
  • 20
  • 65
  • 92