Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are primitive types default-initialized to in C?

Tags:

c

ios

llvm-3.0

I just had Apple's C/C++ compiler initialize a float to a non-zero value (approx "-0.1").

That was a big surprise - and only happened occasionally (but 100% repeatably, if you ran through the same function calls / args beforehand). It took a long time to track down (using assertions).

I'd thought floats were zero-initialized. Googling suggests that I was thinking of C++ (which of course is much more precise about this stuff - c.f. SO: What are primitive types default-initialized to in C++? ).

But maybe Apple's excuse here is that their compiler was running in C mode ... so: what about C? What should happen, and (more importantly) what's typical?

(OF COURSE I should have initialized it manually - I normally do - but in this one case I failed. I didn't expect it to blow up, though!)

(Google is proving worse than useless for any discussion of this - their current search refuses to show "C" without "C++". Keeps deciding I'm too stupid, and ignoring even my input even when running in advanced mode)


Here's the actual source example where it happened. At first I thought there might be a problem with definitions of MAX and ABS (maybe MAX(ABS,ABS) doesnt always do what you'd expect?) ... but digging with assertions and debugger, I eventually found it was the missing initialization - that float was getting init'd to non-zero value VERY occasionally):

float crossedVectorX = ... // generates a float
float crossedVectorY = ... // generates a float

float infitesimal; // no manual init
float smallPositiveFloat = 2.0 / MAX( ABS(crossedVectorX), ABS(crossedVectorY));

// NB: confirmed with debugger + assertions that smallPositiveFloat was always positive

infitesimal += smallPositiveFloat;

NSAssert( infitesimal >= 0.0, @"This is sometimes NOT TRUE" );
like image 713
Adam Avatar asked Apr 10 '12 13:04

Adam


3 Answers

Only objects with static storage duration are initialized to 0 if there is no explicit initializer.

#include <stdio.h>

float f;         // initialized to 0, file scope variables have static storage
static float g;  // initialized to 0

int main(void)
{
    float h;  // not initialized to 0, automatic storage duration
    static float i;  // initialized to 0

    return 0;
}

Objects with automatic storage duration (like h in the example above) that are not explicitly initialized have an indeterminate value. Reading their value is undefined behavior.

EDIT: for the sake of completeness, since C11 objects with thread storage duration are also initialized to 0 if there is no explicit initializer.

like image 156
ouah Avatar answered Sep 21 '22 12:09

ouah


The relevant part of the standard is §6.7.9 paragraph 10:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.

If your variable had thread or static storage duration instead, then the next part of the paragraph would take effect:

If an object that has static or thread 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;

...

I would also note that you should turn on your compiler's warnings (specifically the warning for uninitialized variables), as that should have identified the problem for you immediately.

like image 24
Stephen Canon Avatar answered Sep 17 '22 12:09

Stephen Canon


Static variable would be initialized to zero, but I'm guessing you are talking about a local variable (i.e. stack, or automatic) - these are not initialized for you, but get whatever value is at that memory on the stack.

like image 33
Nikolai Fetissov Avatar answered Sep 17 '22 12:09

Nikolai Fetissov