top | item 10865318

(no title)

stevejones | 10 years ago

The initialisers bit seems downright dangerously wrong. This code:

    uint32_t array[10] = {0};
Does not initialise every element to 0 in the way it would seem to. To see the difference contrast the difference you get when you a) remove the initialiser and b) replace the initialiser with {1}.

discuss

order

Arnavion|10 years ago

>Does not initialise every element to 0 in the way it would seem to.

Yes it does, since atleast C99. As for the others:

a) Removing the initializer will leave the values undefined.

b) Using an initializer of { 1 } will initialize the first element to 1 and the rest to 0.

stevejones|10 years ago

"the way it would seem to"

{} initialises all elements to 0.

{0} initialises the first element to 0 and the rest to 0.

The latter form just introduces confusion.

to3m|10 years ago

When you replace the initialiser with 1, it should only initialse the first element to 1. Objects initialized in this way have unmentioned elements set to 0 or NULL (recursing into aggregates, initialising the first named union member). (See C11 standard, 6.7.9.21. 6.7.9.10 gives the rules for selecting the default value. Aside from the extra syntax, I don't think the rules differ substantially from C89...)

C++ lets you do "uint32_t array[10]={}", which is something C should allow as well, really. But it doesn't.

jzwinck|10 years ago

You may find it distasteful but that has been idiomatic C for more than a decade.

stevejones|10 years ago

I've not seen anyone use that construct anywhere.

jamessu|10 years ago

I was going to remark on this. I've personally run into this writing some C that was built on multiple platforms, one of which had c99 and one of which did not (c89 instead).

I think the real issue here is the inconsistency between C standards on details like this. If you can always assume that your code is built with c99 or later, then use all of its features, but in many cases that's not a realistic assumption.

DerekL|10 years ago

I think that this rule applies to C89 too. I don't have an official copy of the standard, but I found a draft here: http://port70.net/~nsz/c/c89/c89-draft.html#3.5.7

“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.”

gvb|10 years ago

It does if your target system properly zeros bss because, by the rules, array[10] will be placed in bss and bss is zeroed. If you replace the initializer with {1}, you force the compiler to file to a different rule that forces the compiler to explicitly initialize everything to 1.

The problem I've had (and you probably are referring to) is embedded systems that may not properly zero bss. I've also had problems in embedded systems trying to place "array[10] = {0};" into a specific non-bss section (that was really annoying).

In my experience, TFA is good practices generally, but will have problems in corner cases that you run into in deeply embedded systems.

heinrich5991|10 years ago

This is incorrect, `int array[10] = {1}` initializes all but the first element with 0.