473,480 Members | 2,324 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

i++ * i++

#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{

int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49

shouldn't the answer be 12 and 20?

What are the steps the compiler takes to reach the above given output?

Mar 16 '06 #1
35 4720

rohit wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)
This is asking for trouble: consider PRODUCT(2+2), which expands to
2+2*2+2,
ie 8 rather than 16, but that isn't what is causing this particular
problem.
int main()
{

int i =3,j,k;
j = PRODUCT(i++);
This is undefined behaviour: it expands to i++*i++
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49
Ok.
shouldn't the answer be 12 and 20?
No. It can be anything. Yes, anything.
What are the steps the compiler takes to reach the above given output?


Whatever it feels like.

Read the FAQ (starting with question 3.2, which is exactly this
question). (c-faq.com)
You might also find
http://www.eskimo.com/~scs/readings/undef.981105.html useful.

There is actually a perfectly sensible explanation for how the program
might have computed 9 and 49, but trying to second-guess undefined
behaviour is a bad idea.

-thomas

Mar 16 '06 #2
rohit <ro*******@gmail.com> wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{

int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49
For your compiler on your hardware platform, anyway.
shouldn't the answer be 12 and 20?


The answer is that multiple assignments between sequence points yield
undefined behavior.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Mar 16 '06 #3
rohit wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{
int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

The output is 9 and 49

shouldn't the answer be 12 and 20?


You'll want to read http://c-faq.com/expr/
Mar 16 '06 #4
When the compiler sees the i++ the value of i is not actually ever
incremented until after the current statement has executed. So when you
say i++ when i = 3 in that statement it is always 3 in that statement.
You increment the value twice since it says i++ * i++ only in the next
statement. With the ++i the value is incremented before the statement
starts so it sees a 5 from the above line then increments twice to 7 and
then preforms the PRODUCT.

rohit wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{

int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49

shouldn't the answer be 12 and 20?

What are the steps the compiler takes to reach the above given output?

Mar 16 '06 #5
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

rohit wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{

int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49

shouldn't the answer be 12 and 20?
Nope. Because your code modifies an object twice between sequence
points, you've strayed into the realm of "undefined behaviour", and
/any/ answer is the "proper" answer.
What are the steps the compiler takes to reach the above given output?


1) Flip Magic 8 Ball back and forth three times
2) Turn Magic 8 Ball face down
3) Read answer from Magic 8 Ball window

or not

- --

Lew Pitcher, IT Specialist, Corporate Technology Solutions,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEGYuBagVFX4UWr64RAgNlAKDZqIXvfF7lVMFMrR2VP4 m68URgPQCgz7aN
dLkdF+Tl22Pt4hXN3e0yIyw=
=NM3n
-----END PGP SIGNATURE-----
Mar 16 '06 #6
On 2006-03-16, rohit <ro*******@gmail.com> wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{

int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49

shouldn't the answer be 12 and 20?

What are the steps the compiler takes to reach the above given output?


See the FAQ, 3.1

http://c-faq.com/expr/index.html
Mar 16 '06 #7
Steve <gt*****@mail.gatech.edu> wrote:

[ Do not top-post, please. ]
#define PRODUCT(x) (x*x) j = PRODUCT(i++);
k = PRODUCT(++i); The output is 9 and 49

shouldn't the answer be 12 and 20?
When the compiler sees the i++ the value of i is not actually ever
incremented until after the current statement has executed.
This is wrong. What happens when you execute i++ is this:
- the value returned is the value of i before this expression, _and_
- i is incremented.
In which order these are done is not defined; they could even be done in
parallel.
So when you
say i++ when i = 3 in that statement it is always 3 in that statement.


This, too, is wrong.

Richard
Mar 16 '06 #8
rohit wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)
Should be ((x)*(x)) - consider the argument `i + 1`.

Actually, more like "should be `int product(x) { return x*x; }`.
int main()
{

int i =3,j,k;
j = PRODUCT(i++);
BOOM.
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49

shouldn't the answer be 12 and 20?
This a FAQ, so see the C FAQ, eg

http://www.faqs.org/faqs/C-faq/faq/
question 3.2
What are the steps the compiler takes to reach the above given output?


It compiles code for `i++ * i++` assuming that you know what you're
doing. So, at a guess, it multiples i (3) by i (still 3) to get 9.
The it increments i, possibly twice.

The it compiles code for `++i * ++i` ATYKWYD. At a guess, it increments
i, probably twice, then multiplies i (7) by i (still 7) to get 49.

The compiler-writer of course could do things differently. They could
keep a flag for each variable, "increment pending". Then `i++` compiles
as "get the value of i and set the flag", and ";" compiles as "increment
all variables with the flag set, and clear it"; and "++i" compiles as
"increment i, and return the new value". In that case, you'd
get the results 9 and 20.

Or they could compile `i++` as "if the flag is set, report a problem,
plant code to quit the program; otherwise, get the value of i and
set the flag."

--
Chris "sparqling" Dollin
"Who do you serve, and who do you trust?"
Mar 16 '06 #9
This is short sighted because of a few other reasons but wrong is
extremely, just another way to interpret the actions the final result.
Thanks though for pointing it out.

Richard Bos wrote:
Steve <gt*****@mail.gatech.edu> wrote:

[ Do not top-post, please. ]
#define PRODUCT(x) (x*x) j = PRODUCT(i++);
k = PRODUCT(++i); The output is 9 and 49

shouldn't the answer be 12 and 20?

When the compiler sees the i++ the value of i is not actually ever
incremented until after the current statement has executed.


This is wrong. What happens when you execute i++ is this:
- the value returned is the value of i before this expression, _and_
- i is incremented.
In which order these are done is not defined; they could even be done in
parallel.
So when you
say i++ when i = 3 in that statement it is always 3 in that statement.


This, too, is wrong.

Richard

Mar 16 '06 #10
Steve wrote:

[Again, please don't top post. Top-posting corrected for this reply.]
Richard Bos wrote:
Steve <gt*****@mail.gatech.edu> wrote:

[ Do not top-post, please. ]
#define PRODUCT(x) (x*x)

j = PRODUCT(i++);
k = PRODUCT(++i);

The output is 9 and 49

shouldn't the answer be 12 and 20?

When the compiler sees the i++ the value of i is not actually ever
incremented until after the current statement has executed.


This is wrong. What happens when you execute i++ is this:
- the value returned is the value of i before this expression, _and_
- i is incremented.
In which order these are done is not defined; they could even be done in
parallel.
So when you
say i++ when i = 3 in that statement it is always 3 in that statement.

This is short sighted because of a few other reasons but wrong is
extremely, just another way to interpret the actions the final result.
Thanks though for pointing it out.


No, your answer was wrong. Had you said "it appears that your particular
compiler, given the command line flags you specified, has generated code
which behaves as ...", you might have been "right". But your generalized
statement implying that "the meaning of post- and pre-increment is..." is
simply untrue.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Mar 16 '06 #11
Richard Bos wrote:
This is wrong. What happens when you execute i++ is this:
- the value returned is the value of i before this expression, _and_
- i is incremented.
In which order these are done is not defined; they could even be done in
parallel.


Could you explain? When you say "order is not defined" are you talking
about these two?
j = PRODUCT(i++);
k = PRODUCT(++i);


I allways thought that a statement like i++ meant

first use the value of i then increment it

since this is a macro does it change how it works or did i fundamentally
misunderstand.

arnold
Mar 16 '06 #12
arnold wrote:
Richard Bos wrote:
This is wrong. What happens when you execute i++ is this:
- the value returned is the value of i before this expression, _and_
- i is incremented.
In which order these are done is not defined; they could even be done in
parallel.

Could you explain? When you say "order is not defined" are you talking
about these two?

[some context restored]
>>> #define PRODUCT(x) (x*x)
>>> j = PRODUCT(i++);
>>> k = PRODUCT(++i);


I allways thought that a statement like i++ meant

first use the value of i then increment it

since this is a macro does it change how it works or did i fundamentally
misunderstand.

Well, it's not the individual applications of ++ (whether prefix or
postfix) that are a problem, it's the fact that multiple side effects
occur without an intervening sequence point.

Consider the expansions of the expressions above:

PRODUCT(i++) => i++ * i++ and
PRODUCT(++i) => ++i * ++i

in both cases the variable `i' is side affected (did I really say `side
affected'?) twice with no intervening sequence point; since the order in
which things occur is specifically undefined, the overall behavior is
undefined as well.

The C standard, *could*, of course, have defined the order. But it
doesn't. [And that's not likely to change.]

HTH,
--ag
--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com
"You can't KISS* unless you MISS**"
[*-Keep it simple, stupid. **-Make it simple, stupid.]
Mar 16 '06 #13
arnold <ar****@example.net> wrote:
I allways thought that a statement like i++ meant

first use the value of i then increment it
No, that's not it. It means "increment i" and also "the result of the
expression is the value that i had before being incremented". This
implies nothing at all about the order in which the increment or the use
of the value of the expression occur. It's entirely possible that the
compiler will generate code to store off the value of i, increment i
immediately, and then use that temporary value in another expression.
Or alternatively, generate code to increment i first, then make a copy
and subtract one from the copy. Or, alternatively, generate a machine
code instruction that performs the increment simultaneously with using
the original value in another expression.

More importantly, your macro expands to increment i twice, not just
once. The variable i is therefore modified twice, in an undefined order
and perhaps even in parallel, and the result is therefore completely
undefined.
since this is a macro does it change how it works or did i fundamentally
misunderstand.


The macro just expanded PRODUCT(i++) to "i++ * i++", which I assume you
knew, since you wrote the expanded form in the subject line. It's the
multiple modifications to i between sequence points that yield the
undefined behavior.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Mar 16 '06 #14

Chris Smith wrote:
The macro just expanded PRODUCT(i++) to "i++ * i++", which I assume you
knew, since you wrote the expanded form in the subject line. It's the
multiple modifications to i between sequence points that yield the
undefined behavior.
Chris, it wasn't me, it was this other guy called rohit, the OP:)

More importantly, your macro expands to increment i twice, not just
once. The variable i is therefore modified twice, in an undefined order
and perhaps even in parallel, and the result is therefore completely
undefined.
The reason i++ is used twice is because its a macro? dont know much
about macros:( meaning the argument is literally copied into the
expression of the macro hence being duplicated?

So if it had been a function, it would be given the value i and then, in
the next call, i+2. That would have given the values 9 and 25, and there
would be no undefined behaviour. correct or mistaken again?
arnold <ar****@example.net> wrote:
I allways thought that a statement like i++ meant

first use the value of i then increment it

No, that's not it. It means "increment i" and also "the result of the
expression is the value that i had before being incremented". This
implies nothing at all about the order in which the increment or the use
of the value of the expression occur. It's entirely possible that the
compiler will generate code to store off the value of i, increment i
immediately, and then use that temporary value in another expression.
Or alternatively, generate code to increment i first, then make a copy
and subtract one from the copy. Or, alternatively, generate a machine
code instruction that performs the increment simultaneously with using
the original value in another expression.


ok, see. so logically, within one expression, that would mean

use value of i, in the next expression containing i use i+1

let me check if I understand, an expression of the form

(((i_1++ - b) / 3) + i_2++) + c-i_3)

would then mean

i_1 expression: use value of i_1,
i_2 expression: use value of i_1+1,
i_3 expression: use value of i_1+2
But since the OP's expression uses macro it al changes and leads to
undefined behaviour.

If this is correct the I think I understand,

arnold
Mar 16 '06 #15
On 16 Mar 2006 07:49:12 -0800, in comp.lang.c , "rohit"
<ro*******@gmail.com> wrote:
#define PRODUCT(x) (x*x)
j = PRODUCT(i++);
The output is 9 and 49
shouldn't the answer be 12 and 20?


this is a FAQ

Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Mar 16 '06 #16
On Thu, 16 Mar 2006 23:14:33 +0100, in comp.lang.c , arnold
<ar****@example.net> wrote:
The reason i++ is used twice is because its a macro?
Not really - its used twice because thats what the OP programmed for.
dont know much
about macros:( meaning the argument is literally copied into the
expression of the macro hence being duplicated?
Yes, a macro is a literal text replacement. In this case PRODUCT(i++)
is literally replaced by i++ * i++
So if it had been a function, it would be given the value i and then, in
the next call, i+2. That would have given the values 9 and 25, and there
would be no undefined behaviour. correct or mistaken again?


If it had been a function it would have been unspecified which
increment was done first, but the result would have been well defined.
This is because although the order of evaluation of function arguments
is unspecified, there's a sequence point at the function call.
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Mar 16 '06 #17
Mark McIntyre <ma**********@spamcop.net> writes:
On Thu, 16 Mar 2006 23:14:33 +0100, in comp.lang.c , arnold
<ar****@example.net> wrote:
The reason i++ is used twice is because its a macro?


Not really - its used twice because thats what the OP programmed for.
dont know much
about macros:( meaning the argument is literally copied into the
expression of the macro hence being duplicated?


Yes, a macro is a literal text replacement. In this case PRODUCT(i++)
is literally replaced by i++ * i++
So if it had been a function, it would be given the value i and then, in
the next call, i+2. That would have given the values 9 and 25, and there
would be no undefined behaviour. correct or mistaken again?


If it had been a function it would have been unspecified which
increment was done first, but the result would have been well defined.
This is because although the order of evaluation of function arguments
is unspecified, there's a sequence point at the function call.


Yes, but there are no sequence points between the evaluations of the
arguments. This:
func(i++, i++);
invokes undefined behavior because it modifies i twice between
sequence points (regardless of what happens inside func()).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 16 '06 #18
arnold <ar****@example.net> writes:
Chris Smith wrote:
> The macro just expanded PRODUCT(i++) to "i++ * i++", which I assume you
> knew, since you wrote the expanded form in the subject line. It's the
> multiple modifications to i between sequence points that yield the
> undefined behavior.
Chris, it wasn't me, it was this other guy called rohit, the OP:)

> More importantly, your macro expands to increment i twice, not just
> once. The variable i is therefore modified twice, in an undefined order
> and perhaps even in parallel, and the result is therefore completely
> undefined.


The reason i++ is used twice is because its a macro? dont know much
about macros:( meaning the argument is literally copied into the
expression of the macro hence being duplicated?


The reason i++ is used twice is because of what the macro expands to.

Macro expansion is just textual replacement. It works on tokens, not
on expressions.

Consider this program, which demonstrates that Douglas Adams was
right, even without using base 13:
================================
#include <stdio.h>

#define SIX 1+5
#define NINE 8+1

int main(void)
{
printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
return 0;
}
================================

See if you can figure out what the output should be, and why, without
running it. Then compile and run it, and see if you were correct.
So if it had been a function, it would be given the value i and then,
in the next call, i+2. That would have given the values 9 and 25, and
there would be no undefined behaviour. correct or mistaken again?


Mistaken; see my other response in this thread.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 16 '06 #19
Mark McIntyre wrote:

Sorry but what you are saying did not make things cleare for me, so let
me try summarise it a little differently.
Yes, a macro is a literal text replacement. In this case PRODUCT(i++)
is literally replaced by i++ * i++
a literal replacement for each user of the paramter argument?
So, if the paramtere had been: (i++/23) then the expression would have been

(i++/23) * (i++/23)

If it had been a function it would have been unspecified which
increment was done first, but the result would have been well defined.
This is because although the order of evaluation of function arguments
is unspecified, there's a sequence point at the function call.


Just to make sure I understand you correctly, given the following

func1(int x) { return(x * x); }

i=3;
func1(i++); -> return(3 * 3) => 9
func1(++i); -> return(5 * 5) => 25

So the compiler can optimise, reorganise how ever it likes but the
logical effect of it is as described above, correct?

arnold
Mar 16 '06 #20
Keith Thompson <ks***@mib.org> writes:
[...]
Macro expansion is just textual replacement. It works on tokens, not
on expressions.

Consider this program, which demonstrates that Douglas Adams was
right, even without using base 13:
================================
#include <stdio.h>

#define SIX 1+5
#define NINE 8+1

int main(void)
{
printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
return 0;
}
================================


Which is why, in a macro definition, each reference to each argument
should normally be parenthesized, as should the entire expansion.

For example, this:

#define SUM(x, y) x + y

is potentially very dangerous; it should be:

#define SUM(x, y) ((x) + (y))

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 17 '06 #21
arnold wrote:
Just to make sure I understand you correctly, given the following

func1(int x) { return(x * x); }

i=3;
func1(i++); -> return(3 * 3) => 9
func1(++i); -> return(5 * 5) => 25

So the compiler can optimise, reorganise how ever it likes but the
logical effect of it is as described above, correct?


A couple of follow up questions, I was reading the faq on expressions
and some questions came to mind about it.

What you are saying about undefined behaviour is that, if f.ex. an i++
or ++i is used twice in an expression it causes undefined behaviour,
such as by now the famous
i++ * i++
but if its
i++ * j++
then its defined

in question 3.3 it is stated

"neither i++ nor ++i is the same as i+1. If you want to increment i, use
i=i+1, i+=1, i++, or ++i, not some combination."

I am not sure I understand it, is that what I said above, dont use a
variable twice in an expression?

question 3.4

"Operator precedence and explicit parentheses impose only a partial
ordering on the evaluation of an expression."
I dont quite understand this, If I write

((3 + 4) * 2)

in my mind, the paretheses causes the following evaluation

(3 + 2) => 5 then
(5 * 2) => 10

because the second statement can not be evaluated before the first is
evaluated. So does the fact contradict this assumption?

arnold
Mar 17 '06 #22
arnold <ar****@example.net> writes:
arnold wrote:
Just to make sure I understand you correctly, given the following
func1(int x) { return(x * x); }
i=3;
func1(i++); -> return(3 * 3) => 9
func1(++i); -> return(5 * 5) => 25
So the compiler can optimise, reorganise how ever it likes but the
logical effect of it is as described above, correct?
A couple of follow up questions, I was reading the faq on expressions
and some questions came to mind about it.

What you are saying about undefined behaviour is that, if f.ex. an i++
or ++i is used twice in an expression it causes undefined behaviour,
such as by now the famous
i++ * i++
but if its
i++ * j++
then its defined


Right. Note that, in some more complex cases, it can be difficult to
determine whether an expression exhibits undefined behavior just by
looking at it. For example:

arr[i]++ * arr[j]++

is ok if i != j, but if they're equal, it exhibits undefined behavior
(because it modifies an object, namely arr[i], twice).
in question 3.3 it is stated

"neither i++ nor ++i is the same as i+1. If you want to increment i,
use i=i+1, i+=1, i++, or ++i, not some combination."

I am not sure I understand it, is that what I said above, dont use a
variable twice in an expression?
Using a variable twice in an expression is ok. *Modifying* a variable
twice in an expression is not. More precisely, modifying a variable
twice without an intervening sequence point invokes undefined
behavior. (Many expressions don't have sequence points within them.)
question 3.4

"Operator precedence and explicit parentheses impose only a partial
ordering on the evaluation of an expression."
I dont quite understand this, If I write

((3 + 4) * 2)

in my mind, the paretheses causes the following evaluation

(3 + 2) => 5 then
(5 * 2) => 10

because the second statement can not be evaluated before the first is
evaluated. So does the fact contradict this assumption?


Given ((3 + 4) * 2), the compiler is free to replace the entire
expression with a literal 14, so the order of evaluation isn't
visible.

But consider the case where the operands are function calls rather than
integer constants:

((f3() + f4()) * f2())

The addition cannot be performed until after both f3() and f4() have
been called, because until then there's nothing for it to add.
Likewise, the multiplication cannot be performed until all three
functions have been called.

*But*, there is no defined ordering on the function calls themselves.
Regardless of operator precedence and parentheses, the function calls
could occur in any order:

f3(), f4(), f2()
f3(), f2(), f4()
f4(), f3(), f2()
f4(), f2(), f3()
f2(), f3(), f4()
f2(), f4(), f3()

The compiler can generate code to call all three functions in any
arbitrary order, save the results, and then perform the addition and
multiplication. Precedence and parentheses only control which
operators take which operands.

This can be significant if the functions have side effects (such as
output).

The "+" and "*" operators themselves have no side effects, but
consider the case of passing function call results to functions.
Replacing "+" by add() and "*" by mult():

mult(add(f3(), f4()), f2())

Here we have 5 function calls, but not all orderings are allowed,
since a function can't be called until its arguments are available.
The ordering constraints are:

f3() and f4() must be called before add()
add() and f2() must be called before mult()

This reduces the 120 (5 factorial) possible orderings to some smaller
number that I'm too lazy to figure out.

And I'm sure that's a *lot* more than you wanted to know.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 17 '06 #23
Lew Pitcher wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

rohit wrote:
#include <stdio.h>
#define PRODUCT(x) (x*x)

int main()
{

int i =3,j,k;
j = PRODUCT(i++);
k = PRODUCT(++i);

printf("\n%d %d", j,k);

return (0);
}

-----------------------------------------------------------
The output is 9 and 49

shouldn't the answer be 12 and 20?


Nope. Because your code modifies an object twice between sequence
points, you've strayed into the realm of "undefined behaviour", and
/any/ answer is the "proper" answer.

IMHO it is too bad that the C standard can *not* specify that
when you modiy an object twice between sequence points...
a hand will come out of the screen and bitch-slap you.
--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+
Mar 17 '06 #24
arnold <ar****@example.net> wrote:
Chris Smith wrote:
No, that's not it. It means "increment i" and also "the result of the
expression is the value that i had before being incremented". This
implies nothing at all about the order in which the increment or the use
of the value of the expression occur. It's entirely possible that the
compiler will generate code to store off the value of i, increment i
immediately, and then use that temporary value in another expression.
Or alternatively, generate code to increment i first, then make a copy
and subtract one from the copy. Or, alternatively, generate a machine
code instruction that performs the increment simultaneously with using
the original value in another expression.
ok, see. so logically, within one expression, that would mean

use value of i, in the next expression containing i use i+1


No. For _correct_ code, it could be expressed somewhat inaccurately as
something like

use value of i, starting with the next _full_ expression containing i
use i+1

However...
let me check if I understand, an expression of the form

(((i_1++ - b) / 3) + i_2++) + c-i_3)

would then mean

i_1 expression: use value of i_1,
i_2 expression: use value of i_1+1,
i_3 expression: use value of i_1+2
i_1, i_2 and i_3 are not full expressions, they are sub-expressions of
the whole line.
Actually, "full expression" is misleading. The real sticking point is
"between sequence points". The end of a statement is a sequence point,
but so are some select operators such as the logical (&&, ||) and comma
operators, and the actual call of a function, _after_ all its operands
have been determined, and some others. The * operator, however, is not,
and neither is any of the operators in your line above.

The real meaning of i++ is

evaluate to the value of i, and as a side effect, increment i

and that of ++i is

evaluate to the value of i plus one, and as a side effect, increment i

In neither of these cases is there any guarantee about the order in
which the the evaluation and the side effect are performed; and all side
effects _may_ be done just after the previous sequence point (statement
start, logical operator) and they _may_ be done just before the next
sequence point (end of the statement, function call), or they may be
done as a left-to-right reading of the code would indicate, or they may
even be shoved off to a parallel processor and done at the same time as
the main value of the expression is calculated. Or worse.
But since the OP's expression uses macro it al changes and leads to
undefined behaviour.


The macro _as such_ has nothing to do with it. The problem is that
_this_ macro, applied as it is, expands to

i++ * i++

and _that_ expression causes the undefined behaviour. It would do so if
it were entered straight into the code just as much as when it comes
from a macro.

Richard
Mar 17 '06 #25


Thanks, with your and Keiths replies I think I understand now.

cheers.
Mar 17 '06 #26
Hi Rohit,
Compiler always executing the program sequentially. But, macros having
some side effects. I think this is already known by u very well.
Without compiler permission it will change the values of the variable.

See how,

Compiler start execution from int i=3, on

then it comes to the j = PRODUCT(i++);

then this is as it is submitted to the macro then u'r macro became

#define PRODUCT(i++) (i++ * i++);

now i = 3, so 3++ * 3++
so 3*3 =9 now j became 9 but i will become 5 correct becuse i++ and i++
in macro;

Then it comes to the second k = PRODUCT(++i);

this is ++i * ++i correct i is already 4 then pre increament ++i then
i=6 and then ++i the i=7

then 7*7 =49

Correct.
Regards,
Ravi Nakidi,
S/w Engg

Mar 17 '06 #27
Keith Thompson wrote:
Given ((3 + 4) * 2), the compiler is free to replace the entire
expression with a literal 14, so the order of evaluation isn't
visible.
I understand. (So you know, my example was simplified as imagine an
expression where variables had the following values, i could have used
variable names, but for some reason I did not.
And I'm sure that's a *lot* more than you wanted to know.


No, it was exactly the explanation I was looking for.

arnold
Mar 17 '06 #28
Ravi Nakidi <la******@gmail.com> wrote:
Compiler start execution from int i=3, on

then it comes to the j = PRODUCT(i++);

then this is as it is submitted to the macro then u'r macro became

#define PRODUCT(i++) (i++ * i++);

now i = 3, so 3++ * 3++
so 3*3 =9 now j became 9 but i will become 5 correct becuse i++ and i++
in macro;

Then it comes to the second k = PRODUCT(++i);

this is ++i * ++i correct i is already 4 then pre increament ++i then
i=6 and then ++i the i=7

then 7*7 =49


That's certainly one of the infinite number of things that a conforming
compiler could generate from that code. However, it's no more correct
than the compiler generating generating an answer of -1234567890. There
are multiple assignments between sequence points. The result is
undefined. Period. That's really all there is to it.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Mar 17 '06 #29
On Thu, 16 Mar 2006 23:10:24 GMT, in comp.lang.c , Keith Thompson
<ks***@mib.org> wrote:
Yes, but there are no sequence points between the evaluations of the
arguments. This:
func(i++, i++);
invokes undefined behavior because it modifies i twice between
sequence points (regardless of what happens inside func()).


You're right of course. FAQ 3.2
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Mar 18 '06 #30
On Fri, 17 Mar 2006 00:28:33 +0100, in comp.lang.c , arnold
<ar****@example.net> wrote:
a literal replacement for each user of the paramter argument?
So, if the paramtere had been: (i++/23) then the expression would have been

(i++/23) * (i++/23)
Yes.
if you have
#define MACRO (x) (x*x)

and then
MACRO(3+4) ;
it expands to

3+4 * 3+4;
Just to make sure I understand you correctly, given the following

func1(int x) { return(x * x); }

i=3;
func1(i++); -> return(3 * 3) => 9
func1(++i); -> return(5 * 5) => 25

So the compiler can optimise, reorganise how ever it likes but the
logical effect of it is as described above, correct?


Absolutely. The 'as if' rule. The compiler can optimise it any way it
wants as long as the result of the code is exactly 'as if' it had done
no optimisation.

For instance given
x = func1(3);
the compiler could convert that into
x = 9;
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Mar 18 '06 #31
Mark McIntyre <ma**********@spamcop.net> writes:
On Thu, 16 Mar 2006 23:10:24 GMT, in comp.lang.c , Keith Thompson
<ks***@mib.org> wrote:
Yes, but there are no sequence points between the evaluations of the
arguments. This:
func(i++, i++);
invokes undefined behavior because it modifies i twice between
sequence points (regardless of what happens inside func()).


You're right of course. FAQ 3.2


I thought about citing that, but it doesn't actually illustrate the
point. The statement in FAQ 3.2 is:

printf("%d\n", i++ * i++);

That would still be invalid even if there were sequence points between
argument evaluations, since both modifications of i take place within
the same argument.

In fact, I think that adding

printf("%d %d\n", i++, i++);

to the FAQ might be a good idea.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 18 '06 #32
On 17 Mar 2006 01:23:57 -0800, "Ravi Nakidi" <la******@gmail.com>
wrote:
Hi Rohit,
Compiler always executing the program sequentially. But, macros having
Compilers don't execute programs.
some side effects. I think this is already known by u very well.
Without compiler permission it will change the values of the variable.
I don't think a macro can have a side effect since it is only visible
to the preprocessor and side effects occur during execution.

See how,

Compiler start execution from int i=3, on
Compilers compile programs.

then it comes to the j = PRODUCT(i++);
Given the macro described below, the compiler will not see this
statement. It will see the statement as produced by the preprocessor
which would be
j = (i++ * i++);

When executed, this statement invokes undefined behavior. There is no
way the compiler can generate "correct" machine code since there is no
correct undefined behavior.

Everything that follows is unrelated to the C language as defined by
the standard.

then this is as it is submitted to the macro then u'r macro became

#define PRODUCT(i++) (i++ * i++);

now i = 3, so 3++ * 3++
so 3*3 =9 now j became 9 but i will become 5 correct becuse i++ and i++
in macro;

Then it comes to the second k = PRODUCT(++i);

this is ++i * ++i correct i is already 4 then pre increament ++i then
i=6 and then ++i the i=7

then 7*7 =49

Correct.
Regards,
Ravi Nakidi,
S/w Engg

Remove del for email
Mar 18 '06 #33
Mark McIntyre wrote:

On Fri, 17 Mar 2006 00:28:33 +0100, in comp.lang.c , arnold
<ar****@example.net> wrote:
a literal replacement for each user of the paramter argument?
So, if the paramtere had been: (i++/23) then the expression would have been

(i++/23) * (i++/23)


Yes.
if you have
#define MACRO (x) (x*x)

and then
MACRO(3+4) ;
it expands to

3+4 * 3+4;


And, in case it's missed by newbies, the above is totally different from
the apparently intended use of returning the square of the parameter.
(The result here being 19, not 49. If you don't understand why, go back
to your manual and re-read "operator precedence". How to solve this is
left as an exercise to the reader.)

[...]

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Mar 20 '06 #34
Barry Schwarz wrote:

On 17 Mar 2006 01:23:57 -0800, "Ravi Nakidi" <la******@gmail.com>
wrote:

[...]
then it comes to the j = PRODUCT(i++);


Given the macro described below, the compiler will not see this
statement. It will see the statement as produced by the preprocessor
which would be
j = (i++ * i++);

When executed, this statement invokes undefined behavior. There is no
way the compiler can generate "correct" machine code since there is no
correct undefined behavior.


Or, one could say that anything generated is "correct" because there is
no way it could be called "incorrect".

[...]

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Mar 20 '06 #35
On Thu, 16 Mar 2006 16:40:41 +0000, Chris Dollin <ke**@hpl.hp.com>
wrote:
<snip: FAQ 3.2>
What are the steps the compiler takes to reach the above given output?


It compiles code for `i++ * i++` assuming that you know what you're
doing. So, at a guess, it multiples i (3) by i (still 3) to get 9.
The it increments i, possibly twice.

The it compiles code for `++i * ++i` ATYKWYD. At a guess, it increments
i, probably twice, then multiplies i (7) by i (still 7) to get 49.

The compiler-writer of course could do things differently. They could
keep a flag for each variable, "increment pending". Then `i++` compiles
as "get the value of i and set the flag", and ";" compiles as "increment
all variables with the flag set, and clear it"; and "++i" compiles as
"increment i, and return the new value". In that case, you'd
get the results 9 and 20.

Or they could compile `i++` as "if the flag is set, report a problem,
plant code to quit the program; otherwise, get the value of i and
set the flag."


Some versions (3.x up) of gcc detect this and give a warning for at
least the simplest and most obvious cases.

I don't know if they do it with a flag per symbol. In principle I
could read the source, it being free, if only I had a few decades of
spare time and a trust fund (or government grant) to live off.

- David.Thompson1 at worldnet.att.net
Mar 27 '06 #36

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
11162
by: William C. White | last post by:
Does anyone know of a way to use PHP /w Authorize.net AIM without using cURL? Our website is hosted on a shared drive and the webhost company doesn't installed additional software (such as cURL)...
2
5764
by: Albert Ahtenberg | last post by:
Hello, I don't know if it is only me but I was sure that header("Location:url") redirects the browser instantly to URL, or at least stops the execution of the code. But appearantely it continues...
3
22950
by: James | last post by:
Hi, I have a form with 2 fields. 'A' 'B' The user completes one of the fields and the form is submitted. On the results page I want to run a query, but this will change subject to which...
0
8424
by: Ollivier Robert | last post by:
Hello, I'm trying to link PHP with Oracle 9.2.0/OCI8 with gcc 3.2.3 on a Solaris9 system. The link succeeds but everytime I try to run php, I get a SEGV from inside the libcnltsh.so library. ...
1
8520
by: Richard Galli | last post by:
I want viewers to compare state laws on a single subject. Imagine a three-column table with a drop-down box on the top. A viewer selects a state from the list, and that state's text fills the...
4
18206
by: Albert Ahtenberg | last post by:
Hello, I have two questions. 1. When the user presses the back button and returns to a form he filled the form is reseted. How do I leave there the values he inserted? 2. When the...
1
6767
by: inderjit S Gabrie | last post by:
Hi all Here is the scenerio ...is it possibly to do this... i am getting valid course dates output on to a web which i have designed ....all is okay so far , look at the following web url ...
2
31332
by: Jack | last post by:
Hi All, What is the PHP equivilent of Oracle bind variables in a SQL statement, e.g. select x from y where z=:parameter Which in asp/jsp would be followed by some statements to bind a value...
3
23520
by: Sandwick | last post by:
I am trying to change the size of a drawing so they are all 3x3. the script below is what i was trying to use to cut it in half ... I get errors. I can display the normal picture but not the...
0
7054
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
6750
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
6993
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5353
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4794
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
2993
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1307
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
567
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
193
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.