views:

561

answers:

6
#include <stdio.h>
int main() {
    int c = c;
    printf("c is %i\n", c);
    return 0;
}

I'm defining an integer variable called c, and I'm assigning its value to itself. But how can this even compile? c hasn't been initialized, so how can its value be assigned to itself? When I run the program, I get c is 0.

I am assuming that the compiler is generating assembly code that is assigning space for the the c variable (when the compiler encounters the int c statement). Then it takes whatever junk value is in that un-initialized space and assigns it back to c. Is this what's happening?

+2  A: 

c has been initialized!

Although this is one line of code, it is in fact initializing c first, then assigning c to it. You are just lucky that the compiler is initializing c to zero for you.

orangeoctopus
-1... misguided and wrong, but still voted highest... the variable `c` in the example shown is not a pointer, but is allocated on the stack.
gnud
What? Who said it had to be a pointer?
Andres Jaan Tack
Disagree -- `c` is uninitialized for me (depending on compiler options), evidenced by differing, non-zero output when running this code.
pilcrow
Andres, I deleted out a part of my post because it was confusing. What I meant to say is that the label of 'c' is "pointing" to some memory, not pointer in the int* sense. Perhaps referencing is a more correct term?
orangeoctopus
-1. The program **does not** initialise c before assigning c to c. It might be 0 sometimes but under different conditions it could be anything else.
Artelius
+27  A: 

I remember quoting this in a previous answer but I can't find it at the moment.

C++03 §3.3.1/1:

The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any), ...

Therefore the variable c is usable even before the initializer part.

Edit: Sorry, you asked about C specifically; though I'm sure there is an equivalent line in there. James McNellis found it:

C99 §6.2.1/7: Any identifier that is not a structure, union, or enumeration tag "has scope that begins just after the completion of its declarator." The declarator is followed by the initializer.

Brian R. Bondy
Spot on! `+1` .......
Prasoon Saurav
Thanks! Excellent explanation!
Vivin Paliath
C99 §6.2.1/7: Any identifier that is not a structure, union, or enumeration tag "has scope that begins just after the completion of its declarator." The declarator is followed by the initializer.
James McNellis
Thanks @James: I added it.
Brian R. Bondy
+5  A: 

It's undefined behavior to use an uninitialized value (§C99 J.2 "The value of an object with automatic storage duration is used while it is indeterminate"). So anything can happen from nasal demons to c = 0, to playing Nethack.

Matthew Flaschen
+11  A: 

Your guess is exactly right. int c pushes space onto the stack for the variable, which is then read from and re-written to for the c = c part (although the compiler may optimize that out). Your compiler is pushing the value on as 0, but this isn't guaranteed to always be the case.

me_and
+1 Nicely explained.
Andres Jaan Tack
Its likely not pushing 0, it just happens to be that the existing stack frame already contains 0 memory. Depending on 0 being there is of course undefined.
Yann Ramin
+1 very helpful!
Vivin Paliath
Much better answer than quoting from the standard.
kirk.burleson
@kirk A lot of people prefer a reference to the standard, so you know it's guaranteed behavior and not just a convention or a coincidence
Michael Mrozek
@Michael - And a lot of people prefer a simple explanation.
kirk.burleson
I can't say I like the phrase *"pushes space onto the stack"*. It is not wrong as such, but...perhaps *"reserves space on the stack"* or *"insures that there is space on the stack"*.
dmckee
@dmckee: Strictly, yes, we move the stack pointer to make sure there's space. I find it much simpler to visualise as pushing space onto the stack though, and I find that an easier explanation to give to people who may not be very familiar with C.
me_and
A: 

Integer variables are initialized automatically to 0.

JaKoPo
No they aren't.
GMan
Well, all *static* and *global* variable (i.e. those that notionally reside in the data segment) are initialized to 0x00 bytes. But neither automatic variable, nor the storage obtained with `malloc` are initialized to anything: they contain what they contain and you have to live it.
dmckee
+2  A: 

The C specification don't assure that variables will be initialized to 0, 0.0 nor "" or ''.

That is a feature of compilers and never you must thrust that will happen.

I always set my IDE/Compiler to warning about that.

Gustavo V