1

I know that uninitialized variables don't have a particular set value, but I want to know how these uninitialized values are actually decided, either by the compiler or at runtime.

I find that if i run the below code, different outputs will occur:

#include <stdio.h>

int main() {
    int *ptr;
    printf("%p\n", ptr);

    return 0;
}

Output: (clang)

$ clang a.c -o a; ./a
0x7fffed5e33c0
$ clang a.c -o a; ./a
0x7ffe81aa8660
...

Output: (gcc)

$ gcc a.c -o a; ./a
(nil)

How exactly are uninitialized values decided?

iocode
  • 59
  • 5
  • 1
    It's the value that happened to be in this memory/register as a consequence of prior code. But note that reading an uninitialized variable is UB and can have any effect, not limited to a weird value. – HolyBlackCat Jan 14 '23 at 09:32
  • Even reading an uninitialized variable results in undefined behavior so your program is not correct. – August Karlstrom Jan 14 '23 at 09:32
  • Part of the answer depends on the compiler and the compilation settings. The underlying reason for uninitialized values is that C is designed with a strong emphasis on performance. The language would be safer, and arguably better, if *all* objects, even those on the stack, were default-initialized, which would fill native types with zeroes. As it is, that `memcpy` was considered too costly at runtime, so that only statically allocated objects are mandatorily initialized.... – Peter - Reinstate Monica Jan 14 '23 at 11:44
  • ... But nothing keeps a compiler from performing *voluntary* initializations of objects with automatic storage duration, and many do so in debug mode because performance doesn't matter then. A list of initialization values for different compilers and types are listed in [this Wikipedia article](https://en.wikipedia.org/wiki/Magic_number_%28programming%29#Debug_values). In these cases, the values you see will be consistent across runs. – Peter - Reinstate Monica Jan 14 '23 at 11:46
  • 2
    Imagine the chalkboard or whiteboard in a classroom. Imagine you're an instructor coming in to teach a class. Sometimes, the board is blank, meaning that the previous instructor (or a janitor) thoroughly erased it. Sometimes, it has leftover writing from a previous class. Sometimes the previous writing is similar (maybe it's usually chemistry); sometimes it's quite different (maybe it's literature). You may even notice patterns from day to day or from week to week, but you can't depend on them, because there's a large random element. (This isn't a perfect analogy, but it's close.) – Steve Summit Jan 14 '23 at 12:33
  • But the essential point is that nobody "decides" anything. In particular, the compiler does *not* say anything like "Oh, this value is uninitialized, so I guess I will do...". Remember, the compiler is generating code which will do something at run time, and it's at run time that the generated code will encounter a variable that's either initialized or uninitialized. – Steve Summit Jan 14 '23 at 13:12
  • The compiler will *not* generate code that tests whether the variable is initialized or not. For one thing there's not generally anyway to make that determination, and for another thing it would be a waste of time. No, the compiler generates code to just blindly fetch the value of the variable, and what you get is whatever happened to be sitting in that register or memory location, which might have been anything. – Steve Summit Jan 14 '23 at 13:12

1 Answers1

2

They are not decided. That's the very point.

So an optimizing compiler might even optimize out reading the value from memory if it knows it is undefined. Or assume it is something convenient. Or release nasal daemons.

So if you want to know what happens, you need to look at the generated machine code, and possibly run the code in disassembly mode under debugger if value used by assembly code is only known at runtime.

hyde
  • 60,639
  • 21
  • 115
  • 176