简体   繁体   中英

Address of uninitialized variable in C?

int main() {

    int num;
    int a = num;
    int b = num;

    printf("%d", a);
    printf("%d", b);

    return 0;
}

I know that the value of a and b could be different and that will be a garbage value as num is not initialized. But, will the address of num remains the same?

The argument is, does the compiler assigns an address when there is an uninitialized variable? So, if I create an application with let say 1,000 int variables that are uninitialized, does that mean the program will use 4 byte * 1,000 when it's executed?

Seeing as nothing gets the address of the variables, they could very well be optimized away entirely. So no, it doesn't mean that declaring 1,000 32-bit ints will use 4,000 bytes.

Compare this , this and this . As you can see, for that compiler and settings, exactly the same binary is generated for all three of the following:

int num;

printf("%d", num);
printf("%d", num);
int num;
int a = num;
int b = num;

printf("%d", a);
printf("%d", b);
int num;
int a = num;
int b = num;
int c = num;

printf("%d", a);
printf("%d", b);

While 4,000 bytes could be reserved, it's by no means required.

It actually has nothing to do with initialization -- the compiler only needs to assign memory (and an address) to a variable if its address is taken (with the unary & operator) and used (if the address is not used, it might be dead-code eliminated away.)

If the address is never taken, then the variable might be optimized away completely. As long as the compiler can generate code that operates as if the variable existed, it is allowed to optimize it away.

In your example, even if you add an initialization for num (eg, make it int num = 2; it might be optimized away and the code turned into just fputs("22", stdout); getting rid of all the variables.

Strictly speaking, the code in the question has undefined behavior because it accesses uninitialized objects. It also has a constraint violation in C99 or later, because it calls printf with no visible declaration.

Because of the undefined behavior, the C standard says literally nothing about how the program will behave. Undefined behavior is "behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements". The standard joke is that it could make demons fly out of your nose. Of course it can't, but the point is that if it did, that would only violate physics and common sense, not the standard.

So let's get rid of the undefined behavior:

#include <stdio.h>
int main(void) {
    int num = 42;
    int a = num;
    int b = num;

    printf("%d\n", a);
    printf("%d\n", b);
}

Section 6.2.4 of the ISO C standard (I'm using the N1570 draft) says:

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime.

So num , a , and b all have unchanging addresses throughout their lifetimes (which is the execution of the main function), and all three addresses are distinct.

That applies to the "abstract machine". An implementation is required to produce behavior as if all that were the case. If it can do that by generating code equivalent to just puts("42\n42") , that's a perfectly valid optimization. Or, less drastically, it could store num , a , and b in the same location (perhaps a CPU register) because it can prove that they always have the same value and their addresses are irrelevant.

If the behavior of the program actually depends on the addresses of num , a , and b , for example if you print the addresses using printf("%p\n", &a) , then that restricts some optimizations. (Incidentally, taking the address of an uninitialized variable is well defined; you might pass that address to a function that initializes it, for example.)

So, if I create an application with let say 1,000 int variables that are uninitialized, does that mean the program will use 4 byte * 1,000 when it's executed?

If you define 1000 int variables, the compiler will generate code that will allocate sizeof (int) bytes for each of them -- unless it can prove that it doesn't need to. If it can generate code that behaves as required without allocating that memory, it can do that. And if the behavior is undefined, then "behaves as required" isn't a requirement at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM