10

Possible Duplicate:
What happens to a declared, uninitialized variable in C? Does it have a value?

Now I'm reading Teach Yourself C in 21 Days. In chapter 3, there is a note like this:

DON'T use a variable that hasn't been initialized. Results can be unpredictable.

Please explain to me why this is the case. The book provide no further clarification about it.

Community
  • 1
  • 1
user774411
  • 1,749
  • 6
  • 28
  • 47
  • 7
    Throw the book away. Get one from here http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list – pmr Oct 16 '11 at 20:02
  • 2
    When you declare a variable in C, it gives you some memory to use, but it doesn't bother setting that memory to zero or whatever, so you might end up with any old junk values in there. Quite a few bugs I've had in C programs have turned out to be caused by uninitialised variables. – marnir Oct 16 '11 at 20:03
  • 2
    @pmr: Be kind to newbie. Take back the -1 – user774411 Oct 16 '11 at 20:04
  • 1
    This seems like a reasonable question, to me. – Cheeso Oct 16 '11 at 20:05
  • @DeeJay Wasn't me. Someone did that for me already. – pmr Oct 16 '11 at 20:06
  • 4
    It's not a bad question; it's a bad book. – SLaks Oct 16 '11 at 20:08
  • @SLaks - well, to be fair, C is a big topic to learn in 21 days. It's going to have had to have cut some corners, right? – Spudley Oct 16 '11 at 20:23
  • @Spudley - I'm pretty sure the K&R book can be read and exercises done in under 21 days – Flexo Oct 16 '11 at 21:50

6 Answers6

8

Because, unless the variable has static storage space, it's initial value is indeterminate. You cannot rely on it being anything as the standard does not define it. Even statically allocated variables should be initialized though. Just initialize your variables and avoid a potential headache in the future. There is no good reason to not initialize a variable, plenty of good reasons to do the opposite.

On a side note, don't trust any book that claims to teach you X programming language in 21 days. They are lying, get yourself a decent book.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • 2
    Could I be pedantic here and say that it's *indeterminate* rather than undefined? – Brian Roach Oct 16 '11 at 20:07
  • 1
    @Brian: I suppose you can, though I don't see the difference :). The value of an uninitialized variable that does not have static storage space is undefined by the standard. I guess that would have been a better way to state it. – Ed S. Oct 16 '11 at 20:10
  • 2
    @EdS `Undefined` is often interpreted as in `undefined behaviour` which means your whole programming isn't real `C` any more, while `indeterminate` means it is OK to do this, but your results will be unpredictable. – pmr Oct 16 '11 at 20:12
  • @pmr: Agreed, indeterminate is accurate. I reread what I wrote and I meant to say that the standard does not define the behavior. Changed it up a bit. – Ed S. Oct 16 '11 at 20:13
  • 2
    "Indeterminate" is the language used by the standard. "Undefined" is normally reserved to talking about _undefined behavior_. Reading a variable that has an _indeterminate_ value causes _undefined behavior_, but the fact that a variable may contain an indeterminate value does not in and of itself cause _undefined behavior_ so keeping these concepts clear and separate is a good thing IMHO. – CB Bailey Oct 16 '11 at 20:14
  • @Charles: Like I said, I agree. – Ed S. Oct 16 '11 at 20:18
  • @EdS.: Sorry, I think I "crossed comments" with you and pmr. – CB Bailey Oct 16 '11 at 20:38
6

When a variable is declared, it will point to a piece of memory.

Accessing the value of the variable will give you the contents of that piece of memory.

However until the variable is initialised, that piece of memory could contain anything. This is why using it is unpredictable.

Other languages may assist you in this area by initialising variables automatically when you assign them, but as a C programmer you are working with a fairly low-level language that makes no assumptions about what you want to do with your program. You as the programmer must explicitly tell the program to do everything.

This means initialising variables, but it also means a lot more besides. For example, in C you need to be very careful that you de-allocate any resources that you allocate once you're finished with them. Other languages will automatically clean up after you when the program finished; but in C if you forget, you'll just end up with memory leaks.

C will let you get do a lot of things that would be difficult or impossible in other languages. But this power also means that you have to take responsibility for the housekeeping tasks that you take for granted in those other languages.

Spudley
  • 166,037
  • 39
  • 233
  • 307
2

You might end up using a variable declared outside the scope of your current method.

Consider the following

int count = 0;

while(count < 500) 
{
   doFunction();
   count ++;
}

...


void doFunction() {

   count = sizeof(someString);
   print(count);

}
Matt Tew
  • 1,581
  • 1
  • 9
  • 15
1

In C the value of an uninitialized variable is indeterminate. This means you don't know its value and it can differ depending on platform and compiler. The same is also true for compounds such as struct and union types.

Why? Sometimes you don't need to initialize a variable as you are going to pass it to a function that fills it and that doesn't care about what is in the variable. You don't want the overhead of initialization imposed upon you.

How? Primitive types can be initialized from literals or function return values.

int i = 0;
int j = foo();

Structures can be zero intialized with the aggregate intializer syntax:

struct Foo { int i; int j; }

struct Foo f = {0};
pmr
  • 58,701
  • 10
  • 113
  • 156
1

In C, using the values of uninitialized automatic variables (non-static locals and parameter variables) that satisfy the requirement for being a register variable is undefined behavior, because such variables values may have been fetched from a register and certain platforms may abort your program if you read such uninitialized values. This includes variables of type unsigned char (this was added to a later C spec, to accommodate these platforms).

Using values of uninitialized automatic variables that do not satisfy the requirement for being a register variable, like variables that have their addresses taken, is fine as long as the C implementation you use hasn't got trap representations for the variable type you use. For example if the variable type is unsigned char, the Standard requires all platforms not to have trap representations stored in such variables, and a read of an indeterminate value from it will always succeed and is not undefined behavior. Types like int or short don't have such guarantees, so your program may crash, depending on the C implementation you use.

Variables of static storage duration are always initialized if you don't do it explicitly, so you don't have to worry here.

For variables of allocated storage duration (malloc ...), the same applies as for automatic variables that don't satisfy the requirements for being a register variable, because in these cases the affected C implementations need to make your program read from memory, and won't run into the problems in which register reads may raise exceptions.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 2
    I thought that reading the value of an object with automatic storage duration is used while it is indeterminate was always undefined behavior. Where does the distinction about meeting `register` requirements come from? – CB Bailey Oct 16 '11 at 20:22
  • @CharlesBailey in C90 it was undefined, in C99 it became well defined (even for variables that *do* satisfy the requirements of `register`), but a DR added the restriction (see [DR338](http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_338.htm)) for C1x. So in C99, it entirely depends on the implementation. *Only* if it has trap representations then reading from an uninitialized variable is undefined behavior, because such variables have indeterminate "values", and such values may be trap representations. C++11 wasn't fixed in time, but perhaps a TC will do. – Johannes Schaub - litb Oct 16 '11 at 20:41
  • @Charles see http://stackoverflow.com/questions/7456812/valgrind-errors-on-simple-c-string-functions/7457025#7457025 – Johannes Schaub - litb Oct 16 '11 at 20:53
1

At the risk of being pedantic, the statement

DON'T use a variable that hasn't been initialized.

is incorrect. If would be better expressed:

Do not use the value of an uninitialised variable.

The language distinguishes between initialisation and assignment, so the first warning is, in that sense over cautious - you need not provide an initialiser for every variable, but you should have either assigned or initialised a variable with a useful and meaningful value before you perform any operations that subsequently use its value.

So the following is fine:

int i ;  // uninitialised variable

i = some_function() ;  // variable is "used" in left of assignment expression.
some_other_function( i ) ; // value of variable is used

even though when some_function() is called i is uninitialised. If you are assigning a variable, you are definitely "using" it (to store the return value in this case); the fact that it is not initialised is irrelevant because you are not using its value.

Now if you adhere to

Do not use the value of an uninitialised variable.

as I have suggested, the reason for this requirement becomes obvious - why would you take the value of a variable without knowing that it contained something meaningful? A valid question might then be "why does C not initialise auto variables with a known value. And possible answers to that would be:

  • Any arbitrary compiler supplied value need not be meaningful in the context of the application - or worse, it may have a meaning that is contrary to the actual state of the application.

  • C was deliberately designed to have no hidden overhead due to its roots as systems programming language - initialisation is only performed when explicitly coded, because it required additional machine instructions and CPU cycles to perform.

Note that static variables are always initialised to zero. .NET languages, such as C# have the concept of an null value, or a variable that contains nothing, and that can be explicitly tested and even assigned. A variable in C cannot contain nothing, but what it contains can be indeterminate, and therefore code that uses its value will behave non-deterministically.

Clifford
  • 88,407
  • 13
  • 85
  • 165