10

I just stumbled upon a behavior which surprised me:

When writing:

int x = x+1;

in a C/C++-program (or even more complex expression involving the newly created variable x) my gcc/g++ compiles without errors. In the above case X is 1 afterwards. Note that there is no variable x in scope by a previous declaration.

So I'd like to know whether this is correct behaviour (and even might be useful in some situation) or just a parser pecularity with my gcc version or gcc in general.

BTW: The following does not work:

int x++;
Murphy
  • 3,827
  • 4
  • 21
  • 35
Ansgar Lampe
  • 630
  • 1
  • 6
  • 10
  • I believe x is getting initialized to 0 by gcc, but you cannot rely on this behaviour as the standard doesn't asks for that. It may on some systems result in garbage. – vidit Mar 22 '12 at 10:09
  • @EdHeal: No I had not enabled the warnings and not --ansi, but both don't change the situation (no warnings issued) – Ansgar Lampe Mar 22 '12 at 10:56
  • 1
    There's a related, legal (but unusual) use: `Node simpleGraph = Node(&simpleGraph);` to create a graph with one node linked cyclically to itself. Or even weirder, `int x = sizeof(x);`. – MSalters Mar 22 '12 at 12:08
  • 1
    Related to: [Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++1y?](http://stackoverflow.com/q/23415661/1708801) and possibly a duplicate of [Does initialization entail lvalue-to-rvalue conversion? Is `int x = x;` UB?](http://stackoverflow.com/q/14935722/1708801). – Shafik Yaghmour Jul 09 '14 at 13:48

8 Answers8

18

With the expression:

int x = x + 1;

the variable x comes into existence at the = sign, which is why you can use it on the right hand side. By "comes into existence", I mean the variable exists but has yet to be assigned a value by the initialiser part.

However, unless you're initialising a variable with static storage duration (e.g., outside of a function), it's undefined behaviour since the x that comes into existence has an arbitrary value.

C++03 has this to say:

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

Example:
int x = 12;
{ int x = x; }
Here the second x is initialized with its own (indeterminate) value.

That second case there is pretty much what you have in your question.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • "comes into existence" seems a bit vague. I think it is already declared before the `=`, otherwise the compiler would complain about using a unknown identifier. But the initialization does of course happend at the `=`. – Gunther Piez Mar 22 '12 at 10:17
  • @drhirsch, I don't think it's vague at all, I've added the bit in the standard that states this. – paxdiablo Mar 22 '12 at 10:28
  • My second sentence in my comment is nonsense (or very bad phrased). I was referring to the phrase "comes into existence", which you use as "point of declaration". It could be understood as "point of initialization", which would be wrong. – Gunther Piez Mar 22 '12 at 11:07
  • @drhirsch, that's probably more my failing than yours, I'll clarify what I meant. – paxdiablo Mar 22 '12 at 11:19
8

It's not, it's undefined behavior.

You're using an uninitialized variable - x. You get 1 out of pure luck, anything could happen.

FYI, in MSVS I get a warning:

Warning 1 warning C4700: uninitialized local variable 'i' used

Also, at run-time, I get an exception, so it's definitely not safe.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
5
int x = x + 1;

is basically

int x;
x = x + 1;

You have just been lucky to have 0 in x.

int x++;

however is not possible in C++ at a parser level! The previous could be parsed but was semantically wrong. The second one can't even be parsed.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
3

In the first case you simply use the value already at the place in memory where the variable is. In your case this seems to be zero, but it can be anything. Using such a construct is a recipe for disaster and hard to find bugs in the future.

For the second case, it's simply a syntax error. You can not mix an expression with a variable declaration like that.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

The variable is defined from the "=" on, so it is valid and when it is globally defined, it is initialized as zero, so in that case it is defined behavior, in others the variable was unintialized as as such still is unitialized (but increased with 1).
Remark that it still is not very sane or useful code.

stefaanv
  • 14,072
  • 2
  • 31
  • 53
1

Your code has two possiblities:

  1. If x is a local variable, you have undefined behavior, since you use the value of an object before its lifetime begins.
  2. If x has static or thread-local lifetime, it is pre-initialized to zero, and your static initialization will reliably set it to 1. This is well-defined.

You may also wish to read my answer that covers related cases, including variables of other types, and variables which are written to before their initialization is completed

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

3.3.1 Point of declaration 1 The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any), except as noted below. [ Example: int x = 12; { int x = x; } Here the second x is initialized with its own (indeterminate) value. —end example ]

The above states so and should have indeterminate value, You are lucky with 1.

Praveen
  • 331
  • 2
  • 9
0

This is undefined behaviour and the compiler should at least to issue a warning. Try to compile using g++ -ansi .... The second example is just a syntax error.

npclaudiu
  • 2,401
  • 1
  • 18
  • 19