2

I'm trying to figure out why initializing an array with int buckets[AS] = { 0 }; is not setting all the elements to zero. Perhaps it is a compiler optimization, in which case would volatile be acceptable? volatile int buckets[AS] = { 0 };.

Second question, why is only the first element initialized to 1 here? Doesn't this fall under:

C99 [$6.7.8/21]

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.

Problem code:

#include <stdio.h>

#define AS 100

int buckets[AS] = { 1 };

int main()
{
    int i;

    for(i = 0; i < AS; i++) {
        printf("%d", buckets[i]);
    }

    return 0;
}

EDIT:

Changing optimization level from -o0 to default eliminates the issue. Working with STM32 Kiel IDE micro-controllers.

EDIT EDIT:

This is the code causing trouble. Compiler optimizing away for loop?

// Initialize this to 1 as when initializing to 0 and clearing some elements are non-zero
// Possibly a compiler bug? Changing optimization level from -o0 to default eliminates the issue
uint16_t pulse_time_hist[NUM_BUCKETS] = {1};

// Resets all values stored in the histogram
void clearHist() {
    unsigned int i;
    for (i = 0; i < NUM_BUCKETS; i++) {
        pulse_time_hist[i] = 0;
    }
}

EDIT EDIT EDIT:

I'm not a compiler guy at all btw. Here is my compiler control string

-c -cpu Cortex-M4.fp -D__EVAL -g -O0 -apcs=interwork -split_sections ...

Running without -c99 currently.

Cœur
  • 37,241
  • 25
  • 195
  • 267
visc
  • 4,794
  • 6
  • 32
  • 58
  • 2
    Second question: The very citation you highlighted dovetails *perfectly* with what you're seeing regarding zero-filling. That is *exactly* what happens with objects that have "static storage duration", and therefore that paragraph is accurate to what you're seeing regarding the first element(s) being populated, the remainder being zero-filled. – WhozCraig Feb 14 '17 at 06:04
  • Thanks. "remainder of the aggregate shall be initialized implicitly" – visc Feb 14 '17 at 06:05
  • You're welcome, "... the same as objects that have static storage duration" =P – WhozCraig Feb 14 '17 at 06:06
  • 1
    Do you have an example of `int buckets[AS] = { 0 };` that does *not* populate with a zero-fill? The link you provided was for the latter question; not the former. [I can't reproduce that issue](http://ideone.com/Djq17R). Are you on some odd embedded architecture or something? Edit: nm. just saw your added question edit. Thanks. – WhozCraig Feb 14 '17 at 06:10
  • 1
    Are you sure your compiler is C99 compliant? This seems like standard-violating behavior. – Joel Cornett Feb 14 '17 at 06:12
  • @JoelCornett I think that toolchain may very well be thumbing it's nose at the standard in some places. Embedded environments (the OPs microcontroller, for example) often do that, unfortunately. Just one of those things embedded world has to live with sometimes. – WhozCraig Feb 14 '17 at 06:14
  • Yes using odd C99 compiler. Cortex M4 based. – visc Feb 14 '17 at 06:15
  • Though it gets a bad rap in many of the comments, the method for doing this from [this answer](http://stackoverflow.com/a/1565469/1322972) I find to be a pure-programmer's solution to an otherwise annoying problem. Either that, or just bite the bullet and do the powers of 2 (select-all,copy,paste,paste,select-all,copy,paste,paste...) to build the size of static initialization you want. If you're embedded, its probably your only option anyway. – WhozCraig Feb 14 '17 at 06:25

3 Answers3

1

In the quotation "... shall be initialized implicitly ..." a value for initialization is not mentioned, so rest of array is initialized by default value, and for number types this default value is 0.

To continue the topic try the following snippet

#include <stdio.h>

#define N 10

int arr1[N];

int main()
{
    int arr2[N];
    int i;

    for (i = 0; i < N; i++) {
        printf("%d ", arr1[i]);
    }
    printf("\n");
    for (i = 0; i < N; i++) {
        printf("%d ", arr2[i]);
    }
    return 0;
}

and try to understand why the output is

enter image description here

i.e. why global/static objects (like arr1) are initialized without initializers, but local/automatic/stack-allocated (like arr2) are not.

UPDATE:

Section 6.7.8 Initialization of C99 standard said:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. 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.

VolAnd
  • 6,367
  • 3
  • 25
  • 43
0

This is because the missing values are automatically initialized to zero. If you want to initialize every element to 1, you need to have this :

int buckets[AS] = {1, 1, 1, ..., 1}; //100 times

which clearly isn't feasible.

You may also want to read this answer as well.

Community
  • 1
  • 1
Jarvis
  • 8,494
  • 3
  • 27
  • 58
0
int buckets[AS] = { 1 };

In which case you can omit some part of the initializer and the corresponding elements will be initialized to 0.

int buckets[AS] = { 1 }; //initialize to 1,0,0,0,0...

If you are trying to initialize all elements of the array to 1 there is a GCC extension you can use with the following syntax:

 int buckets[AS] = {[0 … 99] = 1 };
msc
  • 33,420
  • 29
  • 119
  • 214