Initial Values
If you declare a global value in C, it's implicitly initialized to zero. This technique is very convenient—and would be even more convenient if you could trust that the author of your compiler has read that bit of the spec. If you get memory from any other source, however, this rule doesn't hold.
When you declare a local value, the compiler turns this into a simple increment of the stack top register. The initial value of the variable will be whatever value was set by the last function to use that bit of stack memory.
Two potential problems exist here. The first is that the behavior of using this value uninitialized might be impossible to predict. The second is that it might not be. In general, using a value before initializing it will put your program into an undefined state. In the worst case, it can cause information leak. If you write some code that accidentally uses a value uninitialized after calling an encryption routine, for example, your "random" value from the uninitialized variable might be some part of the encryption key. If your code runs scripts that can read information from the stack, this can be a serious security hole.
A few problems can happen with uninitialized variables. One of the nastiest I've seen is when you start off with code that looks something like this:
int a = 42;
You then decide that a needs to be initialized conditionally to something else, so you copy and paste it inside an if statement:
if ({some condition}) { int a = 42; }
Oops, you meant to declare it outside the if statement so you can use it afterwards, and make sure you give it a default value:
int a = 0; if ({some condition}) { int a = 42; }
Now you have code that compiles, and runs. Most of the time (when condition isn't met), it will work. But the code inside the braces is basically a no-op. It's defining a new variable called a, and assigning 42 to it. As soon as control exits the block, this variable moves out of scope, and the old a, still with a value of 0, returns.
An even more subtle variant occurs when a typo in an initialization causes you to do something like this:
int value = value + 12;
where what you meant was this:
int value = othervalue + 12;
As soon as the compiler has parsed int value, the variable is valid and in-scope. You can read its value, add 12 to it, and assign it back to itself. Unfortunately for you, the value you read is undefined. You have now set value to an undefined value. If you don't read carefully, you think you've initialized it, but you haven't. An optimizing compiler will even remove the +12, and since undefined plus 12 equals undefined, it's equivalent to this:
int value;
If your compiler issues warnings about things being used uninitialized, it should catch these problems. Unfortunately, turning off these warnings is pretty common, because C doesn't have a way of specifying output parameters. Therefore, things like this are relatively common:
int a; call_some_function(&a);
And this may not be an error, because a is used to return some extra output from the function. In other cases, the function will read the value of a, which isn't initialized. A C compiler has no way of knowing whether this is a valid use of a, and so may complain about it being used uninitialized.