21
#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?

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
  • 3
    Unfortunately, it is allowed - you can normally make the compiler emit a warning about it, for example using g++ (but not gcc for some reason) using the -Wall flag produces a warning. –  Jul 13 '10 at 16:51
  • 7
    @Neil, to force an error with gcc, you use `-Werror=uninitialized -Winit-self` – Matthew Flaschen Jul 13 '10 at 17:01

5 Answers5

30

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
  • 339,232
  • 124
  • 596
  • 636
  • 12
    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 Jul 13 '10 at 17:48
11

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
  • 15,158
  • 7
  • 59
  • 96
  • 4
    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 Jul 13 '10 at 16:57
  • 1
    Much better answer than quoting from the standard. – kirk.burleson Jul 13 '10 at 18:13
  • 1
    @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 Jul 15 '10 at 06:35
  • @Michael - And a lot of people prefer a simple explanation. – kirk.burleson Jul 15 '10 at 12:43
  • 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 --- ex-moderator kitten Jul 15 '10 at 17:22
  • @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 Jul 16 '10 at 11:26
5

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
  • 278,309
  • 50
  • 514
  • 539
  • The value is indeterminate, but that is not undefined behaviour. Nasal demons, and Nethack are out. c = 0 is possible (and likely). The behaviour here is defined in a similar way to a random number generator in that although we can't determine the resulting value, we can be guaranteed by the standard that the value is the only thing unknown about this statement. – Michael Gazonda Jul 11 '14 at 18:37
2

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.

Donald Miner
  • 38,889
  • 8
  • 95
  • 118
  • -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 Jul 13 '10 at 16:53
  • 1
    Disagree -- `c` is uninitialized for me (depending on compiler options), evidenced by differing, non-zero output when running this code. – pilcrow Jul 13 '10 at 16:55
  • 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? – Donald Miner Jul 13 '10 at 16:55
  • 1
    -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 Jul 15 '10 at 03:17
2

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
  • 152
  • 1
  • 1
  • 4