Increment Operator

S

Shaguru

Hai, I am new to C. I have a little confused in this program. please
help me.

#include<stdio.h>

int main()
{
int x=1;

x=x++;
printf("x=%d\n",x);
return 0;
}

output is
x=1
please tell Why 1 not 2.
 
B

Bartc

Shaguru said:
Hai, I am new to C. I have a little confused in this program. please
help me.

#include<stdio.h>

int main()
{
int x=1;

x=x++;
printf("x=%d\n",x);
return 0;
}

output is
x=1
please tell Why 1 not 2.

x++ is 1 (x will be 2 until you overwrite it with 1)
++x is 2 (x will be 2)
 
H

Harald van Dijk

Hai, I am new to C. I have a little confused in this program. please
help me.

int x=1;

x=x++;

please tell Why 1 not 2.

x = gives x a new value. x++ also gives x a new value at the same time.
This is not valid, and while your compiler gives you 1, some other
compilers may give you 2 (or something entirely different). Either only
use x++, or use x = x + 1 if you want to increment x.
 
F

Flash Gordon

Bartc said:
x++ is 1 (x will be 2 until you overwrite it with 1)
++x is 2 (x will be 2)

In the above it doesn't matter whether you use x++ or ++x, it is
undefined behaviour either way.

You should have just told the OP that it is trying to modify x twice
which does not make sense in C.
 
B

Bartc

In the above it doesn't matter whether you use x++ or ++x, it is undefined
behaviour either way.

It seemed to be more confusion over x++ and ++x.
You should have just told the OP that it is trying to modify x twice which
does not make sense in C.

There's that too, but I can't see how, in this simple expression, the
compiler can do anything else other than evaluate x++ then assign the result
to x.
 
B

Bartc

Han from China said:
Bartc said:
There's that too, but I can't see how, in this simple expression, the
compiler can do anything else other than evaluate x++ then assign the
result
to x. [for x = x++;]

There are two modifications between sequence points. This is undefined
behavior, in which case anything can happen, such as having 'x' wind up
with the value 666. But let's assume somewhat sane behavior and try to
"reason out" the expression:

x = 5;
x = x++;

With somewhat sane compiler behavior, we're still left deciding
whether to assign 'x' 5 or 6, since either of the two modifications
could occur before the other.

Only if x++ is split up so that other things can happen between getting the
value x, and incrementing (namely, assigning x to x). I suppose it's
possible, but I'd hesitate to call the compiler sane. A programmer would
naturally think of x++ as a semi-atomic operation.
 
J

James Kuyper

Jack said:
Nonsense. The compiler can reject the code completely. Or the
compiler can nip out for a beer, come back, and reformat your hard
disk. Or generate an executable that reformats you hard disk. Or, or
course, the only standby, make Scott Nudds fly out of your nose.

What you can or can't see is not really relevant to what the standard
requires or does not require.

There are really two separate issues: "what does the standard require?"
and "what could plausibly go wrong?". Your messages addresses the first
issue quite well, but I got the distinct impression that the second
issue is actually more relevant to Flash's comment.
 
B

Beej Jorgensen

Jack Klein said:
Or the compiler can nip out for a beer, come back, and reformat your
hard disk.

"It's the compiler that says 'Bad Motherfucker' on it."

-Beej
 
B

Beej Jorgensen

Bartc said:
There's that too, but I can't see how, in this simple expression, the
compiler can do anything else other than evaluate x++ then assign the result
to x.

Consider this point of view: when I say "x = expr", I expect "x" to be
assigned the value of the result of expr.

That's not so unreasonable, right? :)

Well, therefore:

x = 5;
x = x++; // x is assigned 5, because the value of "x++" is 5.

It might seem a little weird to say the value of "x++" is 5, since it
increments to 6, but some quick legwork shows the subsequently
unsurprising:

x = 5;
printf("The value of x++ is %d\n", x++); // "5"

The spec says x can be incremented any time during the expression
"x=x++" once the value of the subexpression "x++" has been determined.

So a couple legal options are (pretend this is some generated assembly
code or something):

x = 5
exprval = x // value of the expression 'x++'
x++ // now x is 6
x = exprval // now x is 5!

or:

x = 5
exprval = x // value of the expression 'x++'
x = exprval // now x is 5
x++ // now x is 6!

But, just in case all this isn't enough, the spec explicitly calls the
behavior undefined, as well.

I find this surprisingly difficult to explain clearly (which might be
the result of me not understanding it--I /think/ I understand it! :)
Maybe someone else can straighten this post up a bit.

-Beej
 
G

Guest

Consider this point of view: when I say "x = expr", I expect "x" to be
assigned the value of the result of expr.

That's not so unreasonable, right? :)

it's a reasonable expectation whilst the behaviour of the
expression is well defined by the standard.
Well, therefore:

  x = 5;
  x = x++;  // x is assigned 5, because the value of "x++" is 5.

It might seem a little weird to say the value of "x++" is 5, since it
increments to 6, but some quick legwork shows the subsequently
unsurprising:

since its Undefined Behaviour nothing the implementaion can do
can really be said to be surprising.

See the rest of the thread.



<snip>
 
G

Guest

Hai, I am new to C. I have a little confused in this program. please
help me.

#include<stdio.h>

int main()
{
int x=1;

x=x++;
printf("x=%d\n",x);
return 0;

}

output is
x=1
please tell Why 1 not 2.


Several people have tackled this but I'm not sure anyone has quite
answered the
question you meant to ask.

For a start lets get rid of the red herring (from your point of view)
of
Undefined Behaviour.

x = x++;

Has Undefined Behaviour. That is the C Language Syandard does not
define the
behaviour of a program with this statement in it. In other words the
Implementor
(the guy who wrote the compiler) can do anything he damn well pleases.
This
includes setting x to 1 or 2 or some other value. Or just crashing.

This is because x is read and written more than once in the same
statement.

So lets discuss this program instead

#include <stdio.h> /* a space after include makes this clearer */

int main (void) /* the void is best practice in C */
{
int x = 1; /* more whitespace makes this more readable */
int new_x;

new_x = x++;
printf ("x=%d new_x=%d\n", x, new_x);

x = 1;
new_x = ++x;
printf ("x=%d new_x=%d\n", x, new_x);

return 0;
}

this prints
x=2 new_x=1
x=2 new_x=2

Why is that? The ++ operator both modifies x and returns a value.
The pre-increment (++x) increments x and returns the incremented
value.
The post-increment (x++) increments x and returns the original value
of x
 
B

Beej Jorgensen

since its Undefined Behaviour nothing the implementaion can do
can really be said to be surprising.

I should have been more clear that the argument that the value "should"
be 6 was a hypothetical position intended to counter the parent poster's
argument that the value would be 5. I thought that seeing an argument
that the value "should" be 5 AND that it "should" be 6 would be a
not-so-subtle hint that it could be either. But I also put in a couple
examples of how the result could be calculated to be 5 or 6. And then,
in case it wasn't clear, I wrote that it was undefined behavior:


So... I think you and I are in agreement on this.
See the rest of the thread.

I'll re-read the thread right after I'm convinced you've read my post. ;)

The challenge, as I saw it, was to present the parent with a more
satisfying answer than "It's undefined, so the compiler could go buy the
New York Islanders and turn them into a winning hockey team, for all you
know!"

-Beej
 
E

Eric Sosman

Bartc said:
[... concerning x = x++ ...]

Only if x++ is split up so that other things can happen between getting the
value x, and incrementing (namely, assigning x to x). I suppose it's
possible, but I'd hesitate to call the compiler sane. A programmer would
naturally think of x++ as a semi-atomic operation.

The programmer you mention should naturally seek another
career. It should be fairly obvious that "other things" happen
during `x++' between the moment when the old value of x is
fetched and the moment when the new value is stored, because
absent those "other things" there could be no new value.
 
B

Bartc

Eric Sosman said:
Bartc said:
[... concerning x = x++ ...]

Only if x++ is split up so that other things can happen between getting
the
value x, and incrementing (namely, assigning x to x). I suppose it's
possible, but I'd hesitate to call the compiler sane. A programmer would
naturally think of x++ as a semi-atomic operation.

The programmer you mention should naturally seek another
career. It should be fairly obvious that "other things" happen
during `x++' between the moment when the old value of x is
fetched and the moment when the new value is stored, because
absent those "other things" there could be no new value.

There's probably a misunderstanding. A typical asm listing of x=x++ might
be:

(1) mov R,[x]
(2) inc [x]
(3) mov [x],R

Line (1) is the fetching of the value of x in x++
Line (2) is the incrementing of the contents of x in x++
Line (3) is the storing of the value fetched in line (1), into x

Clearly there's nothing between Line (1) and (2).

It's possible that some crazy compiler might reverse the order of lines (2)
and (3) for some reasons best known to itself, but it seems obvious to me
that the right-hand-side of an assignment should be evaluated before storing
it in the left-hand-side, which in this case requires no calculation.
 
R

Richard Bos

Bartc said:
x++ is 1 (x will be 2 until you overwrite it with 1)
++x is 2 (x will be 2)

True but irrelevant. x++ on its own is the previous value of x (and x is
increased); ++x is the previous value of x, plus 1 (and x is increased);
but x=x++ has undefined behaviour. Neither the OP nor you should be
surprised if the result of that statement were for x to be 0 or 3, or
for the program to halt. Yet other outcomes are quite legal, although
perhaps less likely.

Richard
 
W

Willem

Bartc wrote:
) There's probably a misunderstanding. A typical asm listing of x=x++ might
) be:
)
) (1) mov R,[x]
) (2) inc [x]
) (3) mov [x],R

Another typical asm listing of x=x++ might be:
(1) mov [x],[x]
(2) inc [x]



And yet another, on a CPU with special post-increment instructions:
(1) mov R,[x]
(2) mpi R,R (move, post-increment)
(3) mov [x],R
In this case, the mpi instruction does the move and the increment
*at the same time*!! This is roughly how it works:

mpi T,S

- The S register output is connected to the T register input
- The S register output is connected to the 1-adder input
- The 1-adder output is connected to the S register input
(A 1-adder immediately puts its input +1 on its output)
- A clock tick is fired, causing each register to take the value of its
input.

Seems perfectly reasonable, yes ?
Of course, the CPU builders didn't add any special checks that the mpi
instruction is not used with the same register as input and output.
That would need extra circuitry, and therefore extra cost.
(Besides, if it were there, then x=x++ would become a trap instruction.)

Now, let's see what happens in the case of " mpi R,R ":

At the clock tick, the input of R has *two* outputs connected to it.
Now, as it happens, the circuitry is such that if two ones or two zeroes
are both connected to an input, then it becomes one or zero respectively,
but if a one and a zero are connected, then the zero wins out(*).
(Of course, this works for each bit separately)

So, basically, you get a bitwise-and of the two outputs.

This means that if you do x=x++, then the result is the bitwise-and
of x and x+1. For example, if x==5, then after x=x++ you have x=4.

And consider yourself lucky, it could also be such that the bits
fluctuate and are semi-random, depending on external factors.

*) I think this is what happens if you have pull-to-ground logic or
whatever it's called.

And yes, CPUs that connects multiple outputs to a register input
simultaneously happens to exist. The 6510 for example.


) Line (1) is the fetching of the value of x in x++
) Line (2) is the incrementing of the contents of x in x++
) Line (3) is the storing of the value fetched in line (1), into x
)
) Clearly there's nothing between Line (1) and (2).
)
) It's possible that some crazy compiler might reverse the order of lines (2)
) and (3) for some reasons best known to itself, but it seems obvious to me
) that the right-hand-side of an assignment should be evaluated before storing
) it in the left-hand-side, which in this case requires no calculation.

Could you explain why this seems obvious to you ? Obviously it does not
seem so for most people.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
W

Willem

Beej Jorgensen wrote:
) But, just in case all this isn't enough, the spec explicitly calls the
) behavior undefined, as well.
)
) I find this surprisingly difficult to explain clearly (which might be
) the result of me not understanding it--I /think/ I understand it! :)
) Maybe someone else can straighten this post up a bit.

The reason the spec explicitly calls it undefined is that other things
could conceivably happen as well. I'm pretty sure that CPUs exist that
have an instruction that does postincrement on one of its operands.

In that case, it's conceivable that the assignment and the increment happen
at the same time, each trying to get their result into the register.

This could cause weird values to come out, or perhaps make the CPU
overheat, or trap, or cause some random other register to be trashed,
or whatever.

So don't do that, you say!

In the case of C, the burden of not-doing-that lies with the programmer,
instead of with the compiler.

(Also see crossthread for a more detailed examplanation)


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Richard Bos

pete said:
They could have made a special case
for simple expressions which logically apparently
could only produce a finite number of possible values,

Could they? How do you want to define "simple", "logically" and
"apparent"?
and declared them "unspecified" instead of "undefined";
but there's no point in encouraging that kind of writing.

True, but even more importantly, there is no way to draw the line where
everybody thinks it should be drawn. I think it is safe to predict that
any attempt at it would have certain c.l.c'ers frothing at the mouth and
resorting to capitals again.

Richard
 
B

Beej Jorgensen

Willem said:
The reason the spec explicitly calls it undefined is that other things
could conceivably happen as well. I'm pretty sure that CPUs exist that
have an instruction that does postincrement on one of its operands.

Definitely--I'd guess this is one of the prime reasons the spec is
written the way it is.
In the case of C, the burden of not-doing-that lies with the
programmer, instead of with the compiler.

That's a good point to make.

-Beej
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top