views:

113

answers:

5

A coding style presentation that I attended lately in office advocated that variables should NOT be assigned (to a default value) when they are defined. Instead, they should be assigned a default value just before their use. So, something like

int a = 0;

should be frowned upon.

Obviously, an example of 'int' is simplistic but the same follows for other types also like pointers etc.

Further, it was also mentioned that the C99 compatible compilers now throw up a warning in the above mentioned case.

The above approach looks useful to me only for structures i.e. you memset them only before use. This would be efficient if the structure is used (or filled) only in an error leg.

For all other cases, I find defining and assigning to a default value a prudent exercise as I have encountered a lot of bugs because of un-initialized pointers both while writing and maintaining code. Further, I believe C++ via constructors also advocates the same approach i.e. define and assign.

I am wondering why(if) C99 standard does not like defining & assigning. Is their any considerable merit in doing what the coding style presentation advocated?

A: 

I sort of concur with the advice, even though I'm not altogether sure the standard says anything about it, and I very much doubt the bit about compiler warnings is true.

The thing is, modern compilers can and do detect the use of uninitialised variables. If you set your variables to default values at initialisation, you lose that detection. And default values can cause bugs too; certainly in the case of your example, int a = 0;. Who says 0 is an appropriate value for a?

In the 1990s, the advice would've been wrong. Nowadays, it's correct.

Michiel Buddingh'
When you say detect, you mean the compiler flags it as a Warning, right? I have not seen a compiler refusing to compile because of un-initialised variables.
Aditya Sehgal
If it were up to me, it'd be a fatal error, but C being the language it is, a warning is probably the only appropriate response.But hey. A variable that's used while assigned its default value (even though it shouldn't be) will not spawn any warning at all.
Michiel Buddingh'
You make an interesting point. However, the only point where it really bothers me is with respect to Pointers. Usually, good written libraries have NULL checks in place and even if they don't the system dumps core exactly at that point. Using un-intialized pointers may cause dumps but to co-relate it the un-initialized pointer is then a difficult task.
Aditya Sehgal
You're probably right, although personally I'm happy to depend on the compiler to save my ass in this regard. Pointers are somewhat unique in that setting them to `NULL` already marks them as invalid. The same can't be set for initializing an `int` as `0`.
Michiel Buddingh'
A: 

I find it highly useful to pre-assign some default data to variables so that i don't have to do (as many) null checks in code.

RCIX
A: 

There's no such requirement (or even guideline that I'm aware of) in C99, nor does the compiler warn you about it. It's simply a matter of style.

As far as coding style is concerned, I think you took things too literally. For example, your statement is right in the following case...

int i = 0;

for (; i < n; i++)
        do_something(i);

... or even in ...

int i = 1;

[some code follows here]

while (i < a)
        do_something(i);

... but there are other cases that, in my mind, are better handled with an early "declare and assign". Consider structures constructed on the stack or various OOP constructs, like in:

struct foo {
        int bar;

        void *private;
};

int my_callback(struct foo *foo)
{
        struct my_struct *my_struct = foo->private;

        [do something with my_struct]

        return 0;
}

Or like in (C99 struct initializers):

void do_something(int a, int b, int c)
{
        struct foo foo = {
                .a        = a,
                .b        = b + 1,
                .c        = c / 2,
        };

        write_foo(&foo);
}
Eduard - Gabriel Munteanu
I have already mentioned about the approach being useful for structures. However, following it as a rule is something I am(was) not able to understand.
Aditya Sehgal
A: 

I have seen so many bugs due to uninitialized pointers that I always advocated to declare each variable with NULL_PTR and each primitivewith some invalid/default value.

Since I work on RTOS and high performance but low resource systems, it is possible that the compilers we use do not catch non-initialized usage. Though I doubt modern compilers can also be relied on 100%.

In large projects where Macro's are extensively used, I have seen rare scenarios where even Kloclwork /Purify have failed to find non-initialized usage.

So I say stick with it as long as you are using plain old C/C++.

Modern languages like .Net can guarantee to initialize varaibles, or give a compiler error for uninitialized variable usage. Following link does a performance analysis and validates that there is a 10-20% performance hit for .NET. The analysis is in quite detail and is explained well.

http://www.codeproject.com/KB/dotnet/DontInitializeVariables.aspx

Naunidh
+1  A: 

Usually I'd recommend initialising variables when they are defined if the value they should have is known, and leave variables uninitialised if the value isn't. Either way, put them as close to their use as scoping rules allow.

Instead, they should be assigned a default value just before their use.

Usually you shouldn't use a default value at all. In C99 you can mix code and declarations, so there's no point defining the variable before you assign a value to it. If you know the value it's supposed to take, then there is no point in having a default value.

Further, it was also mentioned that the C99 compatible compilers now throw up a warning in the above mentioned case.

Not for the case you show - you don't get a warning for having int x = 0;. I strongly suspect that someone got this mixed up. Compilers warn if you use a variable without assigning a value to it, and if you have:

... some code ...

int x;

if ( a )
    x = 1;
else if ( b )
    x = 2;
// oops, forgot the last case else x = 3;

return x * y;

then you will get a warning that x may be used without being initialised, at least with gcc.

You won't get a warning if you assign a value to x before the if, but it is irrelevant whether the assignment is done as an initialiser or as a separate statement.

Unless you have a particular reason to assign the value twice for two of the branches, there's no point assigning the default value to x first, as it stops the compiler warning you that you've covered every branch.

Pete Kirkham