With this piece of code, what gets output?
float aFloat;
NSLog(@"Default value of a float is zero, right? A float = %.3f", aFloat );
(Hint: USUALLY, you’ll get “0.000″. But not always… )
A common expectation
Apple’s C compiler doesn’t always initialize float’s as you might expect.
The C standard has two different aspects to float initialization. One version will set floats to 0.0 *always*. The other version … will set them to random mem contents – which on iOS, for instance, is normaly but not always … 0.0.
(and the C++ equivalent is, of course, more complicated still … depends on the surrounding context of your variables, e.g. are they in a class? how’s that class getting constructed? etc)
e.g. I had to fix the following code, which was running fine 9 times in 10, but crashing/asserting occasionally:
float infitesimal; // In almost all languages, this = 0.0;
float smallPositiveFloat = 0.0001;
infitesimal += smallPositiveFloat;
NSAssert( infitesimal > 0.0, @"Not with Apple's LLVM version 3, it ain't (sometimes) ..." );
Apple should fix this anyway…
UPDATE: As pointed out by Nathan, Build won’t hilight this, but the Static Analyzer *will* (by default). This is great, but like many devs, currently we only use Xcode’s “Analyze…” every few days (and/or the weekly build) – it’s too slow to do “every” build, and it errors on things that you’re forced to do (e.g. it doesn’t understand asynch callbacks, e.g. it doesn’t like dead code that’s sometimes needed to workaround the Xcode debugger).
It doesn’t surprise me that Apple has left their C mode compiling this – it’s slightly annoying, but technically correct, and following standards is a very good thing.
But the question begs: why doesn’t Xcode flag this as a WARNING by default? That would still be standards compliant, and yet reduce the bugginess of many iOS apps.
(I find it very hard to think of real situations today where an iOS or OSX app would actually want to use a float uninitialized – meanwhile, it’s begging for data corruption bugs, security holes, etc)
In the meantime, of course … whenever you see “float something;” without an ” = 0.0;” on the end … well, you know what to do.
A general problem with Objective C
A brief note on the general case: this isn’t just about floats.
The above behaviour is often removed from modern languages – or is reduced in extent (originally I wrote: doesn’t happen in C++. As James points out below, it does happen in C++, my mistake – although I’d still argue it happens less easily / accidentally). The tiny, rare benefit is outweighed by the large, common loss.
Unfortunately, since ObjectiveC is defined as an extension of C … we’re stuck with it.
Ironically, Apple’s choice of Obj-C (rather than – say – Obj-C++) sometimes has the unwanted effect of pushing programmers back to the dark ages, to the days when “the x-y position indicator” was still just a research project.
(Apple brought out their first consumer desktop with a mouse in 1984. C++ launched in 1983 … )
“C++ et al insist every primitive has a defined value.”
This is not correct: in C++, most types of objects are not initialized by default in most contexts. Notably, fundamental type (float, int, etc.) and compound type (pointers, enums, etc.) local variables and data members are left uninitialized by default.
A good compiler should, of course, flag usage of an uninitialized variable wherever it can, though a compiler cannot always trace an object back to its source when pointers (or, in C++, references) are used.
@James – yes, thanks, that was a dumb mistake on my part. Correted.
I was given to understand from every C book I read that:
“A local C variable is always guaranteed to be initialised to garbage by default”.
Sometimes that garbage may be 0!
Sadly, I can’t remember at the moment whether that would also apply to a static local variable, but I think if memory serves that that WOULD be initialised to 0. Check with the standard to be sure.