a[i] = x[a[i]]++

C

Chris Torek

BRG said:
In the statement: k = x[ k ]++; [ ... snippage ]
Moreover, there appears to be nothing in the C standard to prevent
either of the interpretations:
t = k; k = x[t]; x[t]++;

[equivalently: old_val = x[k]++; k = old_val;]
or
k = x[k]; x[k]++;

[The first] is the correct implementation.

This may be the one you prefer (and the one I prefer, too!), but
unless the Standard actually *says* that, the Standard does not
*say* that.

I believe the wording in the C standards (both C89 and C99) can
reasonably be interpreted *not* to say that. In other words, the
Standard does not say what I want it to say. Too bad for me (and
you, too). :) So just write:

old_val = x[k]++;
k = old_val;

when you mean that -- and/or lobby for a future DR or TC and/or a
future C standard to actually *say* that the expression has to mean
what you and I want it to mean.

"If the Standard says that the result depends on the phase of the
moon, the programmer should be prepared to look out the window as
necessary." --me
 
B

BRG

Chris said:
BRG said:
In the statement: k = x[ k ]++;

[ ... snippage ]
Moreover, there appears to be nothing in the C standard to prevent
either of the interpretations:
t = k; k = x[t]; x[t]++;

[equivalently: old_val = x[k]++; k = old_val;]
or
k = x[k]; x[k]++;

xarax said:
[The first] is the correct implementation.

This may be the one you prefer (and the one I prefer, too!), but
unless the Standard actually *says* that, the Standard does not
*say* that.

I agree. I was hoping to find that the C Standard would make this
interpretation correct but I can't see that it does. It seems to me
that it allows either version and this means that we have to treat the
result of this statement as undefined.
I believe the wording in the C standards (both C89 and C99) can
reasonably be interpreted *not* to say that. In other words, the
Standard does not say what I want it to say. Too bad for me (and
you, too). :) So just write:

old_val = x[k]++;
k = old_val;

when you mean that -- and/or lobby for a future DR or TC and/or a
future C standard to actually *say* that the expression has to mean
what you and I want it to mean.

I wonder who we lobby. Maybe there is a Committee member watching this?

Brian Gladman
 
F

Friedhelm Usenet Waitzmann

Old Wolf said:
Going by my formulation of the rule, the read of p
for (p->next = q) may occur after the write of p
in (p = q), so the behaviour is undefined.

You mean, the standard permits that the left operand (i.e. the
lvalue) of the assignment p->next = q is evaluated *after* the
evaluation of the result?

From draft ISO/IEC JTC1/SC22/WG14 N794:

6.3.16 Assignment operators

Syntax

[...]

Constraints

[...]

Semantics


[#3] An assignment operator stores a value in the object
designated by the left operand. An assignment expression
has the value of the left operand after the assignment,
but is not an lvalue. [...] The side effect of updating
the stored value of the left operand shall occur between
the previous and the next sequence point.

[#4] The order of evaluation of the operands is
unspecified.

The working group regarded the order of evaluation of the
operands as worth to be mentioned ([#4]) but left open the less
obvious possibility, that the left operand (i.e. the lvalue)
might not be computed until the result has been computed and used
in another assignment?

[#3] permits that the "side effect of updating the stored value"
may occur late, but it does not say anything about the time, when the
lvalue itself is computed.

Any comments?
 
R

Richard Tobin

Chris Torek said:
"If the Standard says that the result depends on the phase of the
moon, the programmer should be prepared to look out the window as
necessary." --me

This would make phase-of-the-moon programs either trivial or
fiendishly complicated.

-- Richard
 
F

Friedhelm Usenet Waitzmann

Andrey Tarasevich said:
Albert said:
Now the above is using the side effect,
to mix up in one statement
new = x[ old ];
x[ old ] += 1;

It is *not* equivalent to
a = x[ a ] += 1;
because, being a post-increment, the original value of
x[ a ] must be used.

This is completely irrelevant. If you read this thread
carefully, you'll see that the real question is which value of
'a' is used (old or new), not which value of 'x[a]' is
used. The latter is pretty much irrelevant.

The issue with 'a' is present in your version of the
expression just like it is present in the original version. You
haven't changed anything important by replacing post-increment
with compound assignment.


I think, he has: If you replace x[ a ]++ with
(x[ a ] += 1), the following rule regarding the += applies:

From ISO/IEC JTC1/SC22/WG14 N794:

6.3.16.2 Compound assignment

[...]

Semantics

[#3] A compound assignment of the form E1 op= E2
differs from the simple assignment expression
E1 = E1 op (E2) only in that the lvalue E1 is evaluated
only once.

Therefore, in a = (x[ a ] += 1) the prior value of a is
accessed only once before the new value is stored in a,
because 6.3.16.2[#3] garanties that x[a] is not evaluated a
second time. Or I am wrong?
 
P

Peter Nilsson

Albert said:
Peter Nilsson said:
Albert said:
Does anyone here know whether the assignment:

a = x[ a ]++;

I never use a statement like
x++;
on its own.
Why?!

I always do the equivalent (barring the result value)
x += 1;
This shows that it is an assignment, rather than a side effect.


Rather poor reasoning since x++ is idiomatic, and because _all_
statements are _only_ evaluated for their side effects,
assignments or otherwise (e.g. function calls.)


You use side-effect in a politically correct way here.


It's a term defined in the standard...

"Accessing a volatile object, modifying an object, modifying a
file, or calling a function that does any of those operations
are all _side effects_, ..."
I thought the context made clear that is not what I say.
In an expression like (i + j++)
two thing are happening with j, getting its value and the
incrementation which I call a side-effect. (And the use is
not improper, because it is indeed a lasting effect.).

I (think) I understand that. I was pointing out that C turned
assignments and function calls into expression operators. [It's
not the only language to do this, but the consequences do
surprise many people who program other languages.]
This leaves a pointer to x and has its value incremented.

Drat! I meant ": @++ dup @ dup 1+ rot ! ;"
It could be simplified to: @++ 1 over +! ;

I was hoping you would simplify it, although I didn't anticipate
getting my version wrong. ;( But I'm pretty sure what I was
aiming for could be simplified to... : @++ 1 over +! @ ;

Anyway, my point is that, to a Forth programmer, the optimisation
seems obvious. Within C, the same 'obviousness' surrounds the
optimisation of x += 1 to x++; or ++x;.
It is not equivalent to the c-code x += 1;

It was meant to be equivalent to x++;, i.e. (adr -- n) where
adr is the lvalue (address) of x.
Lets discuss @+ which leaves an incremented address
and a content, the equivalent of *p++ in c.

In the context of Forth it is indeed silly to
do
@+ DROP
instead of just
@
This is analogous.

In C it depends on the context: *p++; is silly, however
c = *p++; or f(*p++); isn't.
In the first example you calculate
two results, then throw one away. Instead of just calculating
a result.

But more on topic.
Is my
x += 1;
sufficiently un-idiomatic to get some eyes browsed?

As Keith points out, there are subjective cases where it's valid,
but in general it will raise eyebrows.

It will make the reader think that you're entirely clued up
in C, just as my posted attempt at Forth was obviously naive
from a Forth perspective.
What about
p += sizeof(struct x);

[Again See Keith's comment, but also....]

Note that sizeof(struct x) cannot generally be expected to be 1.
There is no unary auto-increment-by-something-other-than-1
operator in C. So, p += 2; is not un-idiomatic.
 
P

pete

Richard said:
Or to the C Standard committee:

# The type of an assignment expression is the type of the left operand
# unless the left operand has qualified type, in which case it is the
# unqualified version of the type of the left operand.
(From 6.5.16#3. Identical wording in C89.)

What happens is:
a gets (double)(int)3.1
b gets (int)3.1
and the assignments are made in no particular order.
 

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
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top