C FAQ 3.1

C

ccwork

Hi all,
In CFAQ 3.1, it says:

A: Under my compiler, the code

int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it print
56?

Q: ...the language in K&R suggests that the behavior of this expression
is unspecified, the C Standard makes the stronger statement that it is
undefined...

I think this is interesting. What metrics can we use to determine it is
undefined or unspecified? A similar case is:

f(a++, a);

People says the order of evaluation for function arguments is
undefined. Why can't it be unspecified?
 
P

Peter Nilsson

ccwork said:
Hi all,
In CFAQ 3.1, it says:

A: Under my compiler, the code

int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it print
56?

Q: ...the language in K&R suggests that the behavior of this expression
is unspecified, the C Standard makes the stronger statement that it is
undefined...

I think this is interesting. What metrics can we use to determine it
is undefined or unspecified?

Any metric consistent with the Standard(s).
A similar case is:

f(a++, a);

People says the order of evaluation for function arguments is
undefined.

Forget what 'people' say, read what the Standard(s) say.

"The order of evaluation of the function designator, the actual
arguments, and subexpressions within the actual arguments is
unspecified, but there is a sequence point before the actual
call."
Why can't it be unspecified?

The real question is: Why _should_ it be specified?
 
R

Richard Bos

ccwork said:
In CFAQ 3.1, it says:

A: Under my compiler, the code

int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it print
56?

That's funny, in the web version that's question 3.2.
Q: ...the language in K&R suggests that the behavior of this expression
is unspecified, the C Standard makes the stronger statement that it is
undefined...

I think this is interesting. What metrics can we use to determine it is
undefined or unspecified? A similar case is:

If the Standard says the behaviour of some code unspecified, it's
unspecified. If the Standard doesn't define any behaviour, or explicitly
says the behaviour is undefined, it is undefined.
f(a++, a);

People says the order of evaluation for function arguments is
undefined. Why can't it be unspecified?

People say wrong; the _order_ of evaluation _is_ unspecified. That call
does invoke undefined behaviour, but not because of the order of
evaluation. Rather, it modifies a in the first argument, and also reads
a, not for the purpose of determining its new value, in the second
argument. IOW, it modifies a in one expression, and reads it in another
expression which isn't part of the first one. And this without an
intervening sequence point. _That_ is undefined. The order of evaluation
is indeed unspecified.

The difference comes into play when you call code such as

newvalue=compute(pop(&stack), pop(&stack));

where the value of compute depends on the order of the pop()s. This code
does not invoke undefined behaviour, because there's a sequence point
just before each call of pop() - but the order in which the pop()s are
called; and therefore, the order in which the arguments are popped off
the stack; and therefore, the values that get passes to computer; and
therefore, the new value of newvalue; is unspecified.

Richard
 
S

Stan Milam

Peter said:
The real question is: Why _should_ it be specified?

Because it would clear up a lot of confusion, specify exactly what the
behavior should be. I am convinced we have undefined behavior because
K&R were too lazy or in a hurry to specify exactly what should happen in
these now undefined cases.
 
L

Lawrence Kirby

Because it would clear up a lot of confusion, specify exactly what the
behavior should be. I am convinced we have undefined behavior because
K&R were too lazy or in a hurry to specify exactly what should happen in
these now undefined cases.

It is more likely because this freedom gives compilers extra scope for
optimisation. On some architectured the natural calling sequence might
favour left to right evaluation of arguments, on another ot might be right
to left. Some optimisers might find advantages in other arrangements. It
isn't that common for the order of evaluation to cause a problem so making
it unspecified is a reasonable choice.

Lawrence
 
G

Guest

the C Standard makes the stronger statement that it is undefined...
I just want to known why? This makes the stronger??
 
G

Guest

In my VC 6.0
int i = 7;
mov dword ptr [ebp-4],7
printf("%d\n",i++*i++);
mov eax,dword ptr [ebp-4]
imul eax,dword ptr [ebp-4]

contrast another code
<int i =7;
mov dword ptr [ebp-4],7 <printf("%d\n",++i*++i);
mov eax,dword ptr [ebp-4]
add eax,1
mov dword ptr [ebp-4],eax
mov ecx,dword ptr [ebp-4]
add ecx,1
mov dword ptr [ebp-4],ecx
mov edx,dword ptr [ebp-4]
imul edx,dword ptr [ebp-4]
From that ,i summarize :
We get the result regardless of the order of evaluation, no matter
what from right to left or reverse. Do like this need less mem, less
confussion. Most complier operate like this just i known.
 
R

Richard Bos

Lawrence Kirby said:
It is more likely because this freedom gives compilers extra scope for
optimisation. On some architectured the natural calling sequence might
favour left to right evaluation of arguments, on another ot might be right
to left. Some optimisers might find advantages in other arrangements.

In fact, near the end of the web page posted just this morning (in
<[email protected]>), a compiler
writer describes why his compiler uses neither left-to-right nor right-
to-left, but what he calls hardest-first ordering.

Richard
 
M

Michael Wojcik

It is more likely because this freedom gives compilers extra scope for
optimisation. On some architectured the natural calling sequence might
favour left to right evaluation of arguments, on another ot might be right
to left. Some optimisers might find advantages in other arrangements.

In fact, with modern processors, it's quite likely that the optimal
order of evaluation for some function calls will depend on what else
is happening in the surrounding code, so the order might be different
for different calls in a given TU.

With OOE processors and write-back memory caching, it's possible that
even the compiler doesn't know what order evaluation will actually
effectively take place. Should C compilers be forced to insert memory
barriers in code that evaluates function parameters, just so the
order of evaluation can be specified?

I suspect Stan's conviction is way off base, and both K&R and the
committee had excellent reasons for not defining what happens in
every situation.

--
Michael Wojcik (e-mail address removed)

Company Secretary Finance Manager
1) Half-grey haired executives.
2) Must be waist-deep in their field of activities.
3) Must be having the know-how and the do-how of the latest
developments in their respective fields.
-- from "Appointments Vacant" section of Business India
 
J

Jason

ccwork said:
Hi all,
In CFAQ 3.1, it says:

A: Under my compiler, the code

int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it print
56?

It is my understanding that the ++ operator, when placed after the
variable will increment the value of the variable *after* the entire
expression has been evaluated. As such, 49 is the exact value that I
would expect if I were to write this code. However, having said that, I
would hope that I would never write this code, since it is rather
awkward.

-Jason
 
S

Stan Milam

Michael said:
> I suspect Stan's conviction is way off base, and both K&R and the
committee had excellent reasons for not defining what happens in
every situation.

Well, I hope I am not off base. I *love* the C language, but after
years of using the langauge, reading this newsgroup, and reading a lot
of books I have come to the conclusion that these unspecified areas are
the tell-tale remains of a hurriedly written compiler back in the
1970's. You can read for yourself in K&R 2 where the authors admit that
some of the precedence of operators are wrong. However, by the time
anyone really noticed too much code depended on existing precedence
rules. How many times have we heard, said, or written that if something
was "fixed" it would break a lot of existing code? It is sort of like
depenancy lines in a make file must start with a tab. I wish K&R had
taken the time to clarify some of the penumbras that exist in the
language. Of course, they most likely never dreamed the language would
be as popular as it is and on so many platforms.

One good thing can be said of this: you can claim some level of
expertise not only knowing what to do with the language, but knowing
what to avoid too.

Regards,
Stan Milam.
 
F

Flash Gordon

Jason said:
It is my understanding that the ++ operator, when placed after the
variable will increment the value of the variable *after* the entire
expression has been evaluated. As such, 49 is the exact value that I
would expect if I were to write this code. However, having said that, I
would hope that I would never write this code, since it is rather
awkward.

Your understanding is wrong. The variable could be incremented at any
time before the next sequence point, which in this case is when printf
is called. Therefore the compiler could do something really simple like
this...

t = i
inc i
t = t * i
inc i
printf("%d\n", t)

I suspect it could do something even stranger if it was more efficient.
 
A

Arthur J. O'Dwyer

In my VC 6.0
int i = 7;
mov dword ptr [ebp-4],7

This is not C.
contrast another code
<int i =7;
mov dword ptr [ebp-4],7

This is also not C.
We get the result regardless of the order of evaluation,

Incorrect. In the line 'printf("%d", ++i*++i);', we're not even
guaranteed to get /any/ result, much less the same one always, much
less the /right/ one always. The line exhibits undefined behavior,
and in real life, it exhibits different behaviors on different
implementations. (A decent compiler will produce a warning message
for this code, but no compiler is required to.)
no matter
what from right to left or reverse. Do like this need less mem, less
confussion.

I don't quite know what you're trying to say there, but I bet you're
wrong. (I expect you are confused. Which just goes to show that you're
also wrong about the "less confusion" part.)
Most complier operate like this just i known.

You don't know much about "most compilers," then.

-Arthur
 
R

Richard Bos

Jason said:
It is my understanding that the ++ operator, when placed after the
variable will increment the value of the variable *after* the entire
expression has been evaluated.

Your understanding is wrong. The code i++ does two things:
- it increases the value of i;
- it evaluates to the old value of i.
There are no requirements at all about the order in which the program
does these. If the computer can manage it, it's allowed to do them in
parallel.

As for the code i++ * i++, since it invokes undefined behaviour, the
computer is allowed to do both increases in parallel, and crash as a
result. This is actually a good thing: it allows the compiler to
optimise, for example, i++ * j++ as well, without worrying about
intricate expressions that just happen to modify the same object twice.

Richard
 
P

Purnank

<snip>
discusssion is about
int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it print
56?

I think this is interesting. What metrics can we use to determine it is
undefined or unspecified? A similar case is:

f(a++, a);
Because it would clear up a lot of confusion, specify exactly what the
behavior should be. I am convinced we have undefined behavior because
K&R were too lazy or in a hurry to specify exactly what should happen in
these now undefined cases.


Have you ever thought of writing _your_ own lanugage that *specifies* the
order.

Answer for
i = 7;
printf("%d\n", i++ * i++);

i++ is post increment,
after every thing is done, do increment.
so
step 1)
i * i
( two ++ operatore are pending,
step 2)
%d <== i * i = 49
now everything for the calculation is over,
do the two ++

Print 49,

Moral of the story,
i = 7;
printf("II = %d\n", i++ * i++);

k = 7;
printf("KK = %d\n", (++k) * (++k));

m = 7;
printf("MM = %d\n", (++m) * (m));

II = 49
KK = 64
MM = 56


Question 2)
Order of f(a++, a);
Have you ever thought of writing _your_ own lanugage that *specifies* the
order.
You are calling a function, f(), with two parameters,
where are these parameters going, STACK ? / Registers ?
(for VXworks first few parameters are in Registers )
The function f() may be external to your module.
And function f() may also be defined in some other lanuguage.
__stdcall is used to write dlls in M$ windows and define function types.
(i do not know complete theories for the same )
If the parameters are passed in stack, how are they passed? first paramter
at TOS, last parameter at TOS?,
after the function returns, who will wind up the stack? the one who called
the function ( main() ), or the called function ( f() ) ?

K&R were so goofed up when they did this and hence used a short term to
finish it off.

behaviour of f(a++,a) is undefined.........
 
P

pete

Purnank said:
<snip>
discusssion is about
int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it print
56?

I think this is interesting.
What metrics can we use to determine it is
undefined or unspecified?

It violates a "shall constraint" and is undefined.

N869
6.5 Expressions
[#2] Between the previous and next sequence point an object
shall have its stored value modified at most once by the
evaluation of an expression.

It would only add to your confusion.
Code which exhibits undefined behavior like that,
is so substandard, that it is actually not C code.
It's just gibberish that looks like C code.
 

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

Forum statistics

Threads
474,294
Messages
2,571,518
Members
48,225
Latest member
JasminOrta

Latest Threads

Top