About the spirit of C

Let's begin with an example that illustrate that C is rightly called a low-level language and partially the spirit of C. What's your opinion about the following program:

1
2
3
4
5
6
7
8
int a = 42;
int b;

int
main()
{
    return a + b;
}

This program has two variables a and b and only a is explicitly initialized. What will be the exit code when you compile (and link) it? Is is well-defined? Test it with gcc:

theon$ gcc -o is_that_good_style is_that_good_style.c
theon$ is_that_good_style; echo $?
42
theon$ 

Well it seems that b was zero initialized. Was that luck? Does it depend on the compiler? Does it depend on the hardware or operating system? Would it be better to zero initialize it like that

1
int b = 0; // just to be sure it is zero when we run the program

just to be sure? Actually the above program is perfectly fine. The C standard guarantees that all global variables are initialized before you run the program. And if you don't initialize a global explicitly its value is guaranteed to be zero before execution begins.

Why is the standard so specific?

That is simple: Global variables are either part of the data segment or the bss segment. And in C (and C++) such details are an essential part of the language.

Should I still zero-initialize global variables?

Of course not! The only reason to use a language like C or C++ is that you want a close control of what is going on.

But I disagree!

Well, if you disagree then explain me how you would explicitly zero initialize a global array of integers like that (also read How to initialize array to 0 in C? on stackoverflow):

1
2
3
4
5
6
7
int a[1000];    // array of 1000 (signed) integers

int
main()
{
    /* .... */
}

For small arrays an explicit initialization of an array could be done with the following notation:

1
2
3
4
5
6
7
int a[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // list of initial values

int
main()
{
    /* .... */
}

You certainly would not suggest to adapt that for initializing 1000 arrays elements. Even more insane would be to use a loop like in this example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int a[1000];    // array of 1000 (signed) integers

int
main()
{
    // just to be sure that the global array is zero initialized
    for (int i=0; i<1000; ++i) {
        a[i] = 0;
    }

    /* ... */
}

The zero initialization of the bss segment is free and in C you rely on that. And if a programmer does not care about such things choose a different language.

So is this also ok? Oh my goodness, no!

What do you think about that code:

1
2
3
4
5
6
7
8
int a = 42;

int
main()
{
    int b;
    return a + b;
}

Of course this is insanely wrong! Here b is a local variable, i.e. it is allocated on the stack. There is no way of telling what the initial value of b will be.

But maybe this makes clear why you often read rules like “always explicitly initialize a variable”. By giving dumb rules like that you don't have to explain the difference between global and local variables. Good luck with using C on such a shaky ground. If you use a gun then you should know how to handle that weapon. Recall that trust the programmer is a fundamental principal of C (and C++). Like respect you have earn this trust, it does not come for free.