Evaluation order of function parameters

H

haroon

Consider this function,

void fun (int i, int j)
{
printf ("i = %d : j = %d", i, j);
}

I call it like this:

fun (n++, n);

this when compiled with gcc 4.0 gives following out put:
i = 9 : j = 10

but on gcc 3.4.3 the out put is:
i = 9 : j = 9

although the order of evaluation for function arguments is unspecified
still shouldn't the compiler be consistent in its different versions?
can any one explain why did they change this in version 4 of gcc?

Rgrds,
haroon
 
A

Antonio Contreras

haroon said:
Consider this function,

void fun (int i, int j)
{
printf ("i = %d : j = %d", i, j);
}

I call it like this:

fun (n++, n);

this when compiled with gcc 4.0 gives following out put:
i = 9 : j = 10

but on gcc 3.4.3 the out put is:
i = 9 : j = 9

although the order of evaluation for function arguments is unspecified
still shouldn't the compiler be consistent in its different versions?
can any one explain why did they change this in version 4 of gcc?

Your code invokes undefined behaviour, so the compiler is allowed to do
as it pleases. Why should it be consistent across versions, or even
across different compilations with the same version?
 
A

aakash.joshi

well haroon, i agree with you.
atleast one shud expect similar kind of behavior from the different
versions of the same compiler.

ya thats right ... tht, one shud never write such code in the first
place.
one can never argue .. as the C language doesnt specifies the behavior
of such function calls. it is always compiler specific.

bt i would like to know that wht might be the compiler designer
thinking while changing the behavior. i dnt think its an optimization
issue. any takers for this question ???

regards,
aakash
 
P

pete

haroon said:
Consider this function,

void fun (int i, int j)
{
printf ("i = %d : j = %d", i, j);
}

I call it like this:

fun (n++, n);

this when compiled with gcc 4.0 gives following out put:
i = 9 : j = 10

but on gcc 3.4.3 the out put is:
i = 9 : j = 9

although the order of evaluation for function arguments is unspecified
still shouldn't the compiler be consistent in its different versions?

No.
There's no reason why the code should do anything
that you think it should.
 
E

Ed Vogel

bt i would like to know that wht might be the compiler designer
thinking while changing the behavior. i dnt think its an optimization
issue. any takers for this question ???
The compiler I work on will give different resutls on different
platforms. On a CISC platform, where there an instruction
to do a "fetch and increment", the program would
generate: 9 10. On a RISC platform, where there
is no such instruction, the output is 9 9.

It is possible that newer versions of gcc may notice
that the variable 'n' is never used after the call, and
does not generate code for the increment as that
code is not strictly needed. So, this could be an
optimization.

Ed Vogel
HP/Compaq/DEC C/C++ Engineering
 
C

Chris Dollin

haroon said:
Consider this function,

void fun (int i, int j)
{
printf ("i = %d : j = %d", i, j);
}

I call it like this:

fun (n++, n);

Undefined Behaviour. You modify the variable `n` /and/ access its
value for a purpose other than determinine the new value without
an intervening sequence point: that is explicitly UB.
although the order of evaluation for function arguments is unspecified
still shouldn't the compiler be consistent in its different versions?

There is no such obligation.
 
C

Christopher Benson-Manica

atleast one shud expect similar kind of behavior from the different
versions of the same compiler.

Why would one expect any such thing? Even the same version of the
same compiler can easily and reasonably generate different code. My
Borland 5.4.1 compiler, for example, can be told to use 80486
instructions or Pentium Pro instructions. You want to place bets on
whether the behavior of code exhibiting undefined behavior will be the
same for these two instruction sets?
one can never argue .. as the C language doesnt specifies the behavior
of such function calls. it is always compiler specific.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

"Undefined" means undefined. A compiler/implementation need not
behave in any documented or even reasonable way when faced with such
situations.
 
K

Kenny McCormack

one can never argue .. as the C language doesnt specifies the behavior
of such function calls. it is always compiler specific.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

"Undefined" means undefined. A compiler/implementation need not
behave in any documented or even reasonable way when faced with such
situations.[/QUOTE]

I don't see why you (and other so-called "regulars") bother to post these
bullshit answers. Well, actually, I do. You know perfectly well that to
the OP, they (your answers) are bullshit, but you do it to impress your
"peers" (other so-called "regulars").

It seems to me that a simple, short, crisp:

Not portable. Can't discuss it here. Blah, blah, blah.

is a lot more appropriate - much more likely to help the OP - than is your
long discourse on why it is not covered by the standard. For crying out
loud, the OP has already allowed as how it is non-standard; he doesn't need
to be told that (again & again). Again, a simple "Can't discuss it here"
is to the point, and may even bring a smile to the OP's face.

And that would be a good thing.
 
E

Emmanuel Delahaye

haroon a écrit :
Consider this function,

void fun (int i, int j)
{
printf ("i = %d : j = %d", i, j);
}

I call it like this:

fun (n++, n);

Don't ever do that. Never. The behaviour is not portable. Unary
operators only make sense when used alone.

I you want this

fun (n + 1, n);
n++;

be explicit.
 
E

Emmanuel Delahaye

(e-mail address removed) a écrit :
bt i would like to know that wht might be the compiler designer
thinking while changing the behavior. i dnt think its an optimization
issue. any takers for this question ???

No, it's not a C question. See
 
G

Gordon Burditt

fun (n++, n);

You have invoked the wrath of undefined behavior - changing
and using the value of n without an intervening sequence point
(the comma in a function call is *NOT* a comma operator).
although the order of evaluation for function arguments is unspecified
still shouldn't the compiler be consistent in its different versions?

No, it is not necessary for the output to be consistent in two
runs of the *SAME* program as compiled by the same compiler.
can any one explain why did they change this in version 4 of gcc?

The behavior might also change with different levels of optimization
on the same copy of the same compiler.

Gordon L. Burditt
 
K

Kenny McCormack

You have invoked the wrath of undefined behavior - changing
and using the value of n without an intervening sequence point
(the comma in a function call is *NOT* a comma operator).


No, it is not necessary for the output to be consistent in two
runs of the *SAME* program as compiled by the same compiler.

It is not necessary, 'tis true. But it should work right, anyway.
Note that there *is* a difference between should and necessary (where,
I think, we can interpret "necessary" as "required by law"). For example,
in real life, we should help each other, but we are not required by law to
do so.

Only lawyers and clc "regulars" think the two are synonymous.
The behavior might also change with different levels of optimization
on the same copy of the same compiler.

True. But it *shouldn't* (see above) change unless there's a good reason
for it to do so.
 
D

David Resnick

Kenny said:
It is not necessary, 'tis true. But it should work right, anyway.
Note that there *is* a difference between should and necessary (where,
I think, we can interpret "necessary" as "required by law"). For example,
in real life, we should help each other, but we are not required by law to
do so.

Only lawyers and clc "regulars" think the two are synonymous.


True. But it *shouldn't* (see above) change unless there's a good reason
for it to do so.

In addition to being a troll, I think your posting patterns on clc make
you look a fool. When I voted for google groups to have killfiles, you

and chellapa were mostly what I had in mind (Tisdale being quiet for
a while).

Your argument, if thought through, suggests that a compiler writer/
maintainer should have to have a handy regression suite that tests
all possible instances of undefined/unspecified behavior and verifies
that no outcomes differ with any changes they make. If you
can't see the difficulty with that, well...

-David
 
G

Gordon Burditt

fun (n++, n);
It is not necessary, 'tis true. But it should work right, anyway.

The point is that there is *NO* *DEFINITION* *OF* *WRONG* in this
situation. *ANYTHING* it does is correct. I'll settle for "right"
meaning "not injuring or killing anyone or damaging equipment".
Note that there *is* a difference between should and necessary (where,
I think, we can interpret "necessary" as "required by law"). For example,
in real life, we should help each other, but we are not required by law to
do so.
Only lawyers and clc "regulars" think the two are synonymous.


True. But it *shouldn't* (see above) change unless there's a good reason
for it to do so.

And the good reason may well be is that you wanted optimization, and
it was faster to do things in a different order.

Gordon L. Burditt
 
C

Christian Bau

"haroon said:
Consider this function,

void fun (int i, int j)
{
printf ("i = %d : j = %d", i, j);
}

I call it like this:

fun (n++, n);

this when compiled with gcc 4.0 gives following out put:
i = 9 : j = 10

but on gcc 3.4.3 the out put is:
i = 9 : j = 9

although the order of evaluation for function arguments is unspecified
still shouldn't the compiler be consistent in its different versions?
can any one explain why did they change this in version 4 of gcc?

It is undefined behavior. One could say that you got what you deserved,
but you didn't. If you put that kind of code into production code, it
goes wrong, customers lose money, your company loses money, and you get
fired, that is when you got what you deserved.
 
K

Kenny McCormack

It is not necessary, 'tis true. But it should work right, anyway.

The point is that there is *NO* *DEFINITION* *OF* *WRONG* in this
situation. *ANYTHING* it does is correct. I'll settle for "right"
meaning "not injuring or killing anyone or damaging equipment".[/QUOTE]

But you see, that's the funny thing. According to a lot of the "regulars",
anything, anything is allowed, including re-formatting the hard disk and
blowing up the house. Luckily, you're not as loony as they are.
And the good reason may well be is that you wanted optimization, and
it was faster to do things in a different order.

Agreed. My point is that under stable conditions, it should (see above and
previous posts for what I mean by "should") do the same thing. Of course,
it is not "required" to do so.
 
R

Richard Tobin

Kenny McCormack said:
Agreed. My point is that under stable conditions, it should (see above and
previous posts for what I mean by "should") do the same thing.

What do you mean by "stable"? Obviously the exact same copy of the
compiler is likely to produce the same code tomorrow as today. But
all kinds of minor changes might make it change.

For example, trivial changes to the surrounding code might change the
registers available, resulting in different optimisation choices.

Even compiling the same code with the same compiler on different
releases of the same operating system might cause a change. The
compiler might use qsort() to choose between optimisations, and
different versions of qsort might return different results (because
it's not guaranteed to be stable). This is not just a theoretical
possibility: it was observed when gcc was used as part of the SPEC
benchmarks.

-- Richard
 
R

Richard Bos

The point is that there is *NO* *DEFINITION* *OF* *WRONG* in this
situation. *ANYTHING* it does is correct. I'll settle for "right"
meaning "not injuring or killing anyone or damaging equipment".

But you see, that's the funny thing. According to a lot of the "regulars",
anything, anything is allowed, including re-formatting the hard disk and
blowing up the house. Luckily, you're not as loony as they are.[/QUOTE]

The loon is on the other bank. If a case of UB formats your hard disk,
that's the fault of your OS for not preventing a random program from
doing so, _not_ of the C implementation. Ditto for all other seemingly
ridiculous suggestions.
If you, e.g., write a seemingly random value over a function pointer,
and then jump to it, are you doing this because you made a mistake - or
are you writing low-level kernel code which actually needs this? The
compiler cannot possibly know. The OS, which runs your code, does know
whether or not you're allowed to do this.
It's the implementation's job to let you shoot yourself in the foot, if
you write code to do so. The OS' job is, amongst others, to prevent the
bullet from reaching flesh unless you have Write permission on your own
extremities.

Richard
 

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,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top