Sequence point question (function result semantics) 
Author Message
 Sequence point question (function result semantics)

Quote:




> > >Thanks for the "Standards Requirement".  I'm not knowledgeable enough to
> > >question that a diagnostic must be produced.  But as a programmer in the
> > >real world, if the proper value was placed in c, I'd just redirect the
> > >diagnostic to /dev/null.  The only pertinent question to me is does c
> > >get
> > >the value I expect it to?

> > And I think the answer to that is that it all depends on what you expect
> > and which compiler you are using.

> Well, the obvious answer to what I'd expect from:

> c = (f(x))++;

> is what it _looks_ like it should put in c, namely, f(x).  I'm not
> concerned with what happens to f(x) after that.

You may not be, but the compiler must be. So must the language
specification. Remember that this is only a very simple example; the
specification must deal with all possible uses.

Quote:
>  I don't understand why this should be compiler dependent.
>  The postfix operator++ always increments after assignment.

That's just the point: it doesn't. It increments the operand, and
returns the value before the increment, in either order. Both _must_
happen. So how does the compiler increase the result of a function call?
It can't.

Quote:
> I expect it to be analagous to:

> c = x++;

No, it isn't; x is (presumably) a modifiable lvalue, and thus _can_ be
increased. f(x) isn't, and can't; so asking for it to be increased
anyway is undefined behaviour.

Basically,
  c = f(x)++;
is more analogous to
  int a[10];
  c = a++[4];

Richard
--



Mon, 14 Jul 2003 00:20:58 GMT  
 Sequence point question (function result semantics)


Quote:
>I expect it to be analagous to:

>c = x++;

>which I trust is NOT compiler dependent.

Why? One has undefined behaviour (which the implementor might define in
any way  that she chose) the other has strictly defined semantics as x
must be an lvalue - dereferenced to obtain the rvalue required for the
assignment.

--
Francis Glassborow
See http://www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)
--



Mon, 14 Jul 2003 00:21:05 GMT  
 Sequence point question (function result semantics)

Quote:
>The postfix operator++ always increments after assignment.

No it doesn't.  When the increment happens is compiler-dependent.  All you
know for sure is that both the assignment and in increment happen before
the next sequence point.

--
#include <standard.disclaimer>
 _
Kevin D Quitt  USA 91351-4454           96.37% of all statistics are made up
Per the FCA, this email address may not be added to any commercial mail list
--



Fri, 18 Jul 2003 13:38:37 GMT  
 Sequence point question (function result semantics)

....
Quote:
> >                 c = (foo())++;
....
>   Having read the answers given, I'm a bit confused.  AFAIK, the
> post-fix
> operator++ has lower precedence than the operator=.  Thus c should be
> assigned
> the value of foo() and....  Well that value is incremented but ignored.

You know wrong.  All postfix operators (ary[sub], func(args),
su.mem, psu->mem, ++, --) have the highest precedence,
and assignment operators (=, += etc.) next-to-lowest
(above only comma).

Remembering, of course, that "precedence" controls
only association and binding of operands, but not
strictly sequence of execution; only data dependence
and sequence points control that.  And that not all
syntactic commas are uses of the comma operator.

--
- David.Thompson 1 now at worldnet.att.net
--



Fri, 18 Jul 2003 13:45:02 GMT  
 Sequence point question (function result semantics)

Quote:
> Basically,
>   c = f(x)++;
> is more analogous to
>   int a[10];
>   c = a++[4];

OK, after this discussion AND (re-)reading Peter van der Linden's Expert C
Programming
I admit defeat (and disgust - at the Standard, the Standards' Committee and the
language itself).
I'd re-write the second as:

    int a[10];
    int *pa;
    c = *(p++)[4]; /* or better yet */
    c = *4[p++];

And that'll work fine - it's not a bug, it's a feature!

--Jeff Turner
--



Wed, 23 Jul 2003 12:18:07 GMT  
 Sequence point question (function result semantics)

Quote:


> >The postfix operator++ always increments after assignment.

> No it doesn't.  When the increment happens is compiler-dependent.  All you
> know for sure is that both the assignment and in increment happen before
> the next sequence point.

> --
> #include <standard.disclaimer>
>  _
> Kevin D Quitt  USA 91351-4454           96.37% of all statistics are made up
> Per the FCA, this email address may not be added to any commercial mail list
> --


C'mon this is language lawyering at its worst.

If a == 5 then:

    c = a++;

leaves 5 in c and 6 in a.  If the compiler is poor enough to create a temp
variable
so that the increment can happen before the assignment - I'd get a new compiler
pronto.

--Jeff Turner
--



Wed, 23 Jul 2003 12:18:33 GMT  
 Sequence point question (function result semantics)

Quote:

> Basically,
>   c = f(x)++;
> is more analogous to
>   int a[10];
>   c = a++[4];

> Richard

I think this is a lousy analogy, though I'm not sure anymore whether f(x)++
increments,
hypothetically, the return value of f(x) or the address of the function pointer
f.  In the
latter case, the analogy is actually quite good.  In the former case, f(x)
vanishes at the
semicolon - incremented or not - and assuming a[10] isn't a local array and that
the
closing bracket of its scope does not immediately follow, a[] sticks around.  We
all
know you can't modify an array name's location, nor that of a function pointer -
so
the final statement is undeniably, and for GOOD reason, illegal.

I suppose that since C was developed to be easy for compiler writers the obvious
solution is to write my own compiler that does the logical thing with c = f(x)++.

I'm certainly glad that logic wasn't a deciding factor in writing the C standard!

--Jeff
--



Wed, 23 Jul 2003 12:22:01 GMT  
 Sequence point question (function result semantics)


Quote:
>C'mon this is language lawyering at its worst.

>If a == 5 then:

>    c = a++;

>leaves 5 in c and 6 in a.  If the compiler is poor enough to create a temp
>variable
>so that the increment can happen before the assignment - I'd get a new compiler
>pronto.

There were architectures that had in-memory increments in which case
increment could easily take place before assignment (load value a to
register, in-memory increment a, save register a to c) Of course this
language law but if you want to understand why rules are the way they
are, you have to take into account the unusual.

--
Francis Glassborow
See http://www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)
--



Thu, 24 Jul 2003 02:30:31 GMT  
 Sequence point question (function result semantics)

Quote:



> >C'mon this is language lawyering at its worst.

> >If a == 5 then:

> >    c = a++;

> >leaves 5 in c and 6 in a.  If the compiler is poor enough to create a temp
> >variable
> >so that the increment can happen before the assignment - I'd get a new compiler
> >pronto.

> There were architectures that had in-memory increments in which case
> increment could easily take place before assignment (load value a to
> register, in-memory increment a, save register a to c) Of course this
> language law but if you want to understand why rules are the way they
> are, you have to take into account the unusual.

But that doesn't sound like it delivers into c what it should.  I understand
computer
architectures can support all sorts of complicated atomic executions - no problem
there, but c is getting the value of a.  If the compiler design increments a first,
then
either it puts the result in a different register and "remembers" that a has moved
from one register to another and c is now in the register that used to hold a, or
there
is some sort of temporary created for the incremented value:

temp = a+1;
c = a;
a = temp;

which I would assume to be less efficient regardless of the architecture.  If
someone
can explain an architecture where this can be implemented more efficiently than
doing
the assignment first I'd really be very interested to learn something new about uP
architectures.

    If someone can show me compiler code that makes the first alternative, i.e.
switching
the association of registers and variables, more efficient than the seemingly more
straight-
forward:  c=a;  a++;  then I'd be interested in that also - I understand that this
would be
architecture dependent as well.

    If neither of these can be demonstrated, then I'll put a hex on the standards
committee.
I'm sure it won't be the first.  Maybe, as the old man page writer put it, they
should be
"dogged by a UNIX demon 'til time_t wraps around".

--Jeff Turner
--



Thu, 24 Jul 2003 22:56:15 GMT  
 Sequence point question (function result semantics)

Quote:

> I suppose that since C was developed to be easy for compiler writers
> the obvious solution is to write my own compiler that does the
> logical thing with c = f(x)++.

What on earth might the "logical thing" be?

Quote:
> I'm certainly glad that logic wasn't a deciding factor in writing the
> C standard!

It was.  You should try it before you knock it.
--



Thu, 24 Jul 2003 22:57:04 GMT  
 Sequence point question (function result semantics)


Quote:
>But that doesn't sound like it delivers into c what it should.  I understand
>computer
>architectures can support all sorts of complicated atomic executions - no
>problem
>there, but c is getting the value of a.  If the compiler design increments a
>first,
>then
>either it puts the result in a different register and "remembers" that a has
>moved
>from one register to another and c is now in the register that used to hold a,
>or
>there
>is some sort of temporary created for the incremented value:

>temp = a+1;
>c = a;
>a = temp;

No, you have missed the point. There is no intermediate register, some
machines provided a mechanism whereby a++ actually happened in memory
so:

load a to register
increment a // increase item stored in memory
save register to a

Note that this allows:

load address register with address of a
load 'accumulator' (from memory addressed by register)
increment contents of memory addressed by register
load address register with address of c
save accumulator (to address in address register)

With such an architecture insisting on saving before incrementing is
less efficient.

--
Francis Glassborow
See http://www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)
--



Fri, 25 Jul 2003 13:22:14 GMT  
 Sequence point question (function result semantics)

Quote:

> I'm certainly glad that logic wasn't a deciding factor in writing
> the C standard!

Why don't you just learn the difference between an l-value and an
r-value instead of putting hexes on the standards committee, etc.?

--
--Ed Cashin                     integrit file-verification system:

    Note: If you want me to send you email, don't munge your address.
--



Fri, 25 Jul 2003 13:24:16 GMT  
 Sequence point question (function result semantics)
[re "a = c++"]

Quote:

>>There were architectures that had in-memory increments in which case
>>increment could easily take place before assignment (load value a to
>>register, in-memory increment a, save register a to c) Of course this
>>language law but if you want to understand why rules are the way they
>>are, you have to take into account the unusual.


Quote:

>But that doesn't sound like it delivers into c what it should.  I
>understand computer architectures can support all sorts of complicated
>atomic executions - no problem there, but c is getting the value of a.
>If the compiler design increments a first, then either it puts the
>result in a different register and "remembers" that a has moved from
>one register to another and c is now in the register that used to
>hold a, or there is some sort of temporary created for the incremented
>value:

>temp = a+1;
>c = a;
>a = temp;

>which I would assume to be less efficient regardless of the architecture.

It is not the "compiler design" but rather the machine.  Imagine,
if you will, that the machine has the "ld++" instruction, which
loads from memory while incrementing the memory.  Then:

        c = a++;

compiles to:

        ld++    r1, c  # r1 = c++ (r1 gets previous value)
        st      r1, a  # a = r1

or:

        ld++    r1, c  # r1 = ++c (machine uses preincrement)
        dec     r1     # we wanted the old value
        st      r1, a  # a = r1

Compare this to the "obvious":

        ld      r1, c
        st      r1, a
        inc     r1
        st      r1, c

and you can see that using the "ld++" instruction is always a net
win -- but it always increments "c" before setting "a".

(An actual machine on which this might happen is one with atomic
add, although here the compiler would emit:

        mov     1, r1
        lea     a, r2
        aadd    r1, (r2)

Now r1 holds either the previous value of "a", or the sum.  IBM
built at least one machine with atomic ALU-ops to memory.  Atomic
ops to memory tend to be slow so you would probably want to do this
only for "volatile int"s that are "++"ed.)
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc


--



Sat, 26 Jul 2003 05:02:38 GMT  
 Sequence point question (function result semantics)

Quote:

> But that doesn't sound like it delivers into c what it should.  I understand
> computer
> architectures can support all sorts of complicated atomic executions -
no problem
> there, but c is getting the value of a.  If the compiler design
increments a first,
> then
> either it puts the result in a different register and "remembers" that a
has moved
> from one register to another and c is now in the register that used to
hold a, or
> there
> is some sort of temporary created for the incremented value:

> temp = a+1;
> c = a;
> a = temp;

> which I would assume to be less efficient regardless of the architecture.  If
> someone
> can explain an architecture where this can be implemented more
efficiently than
> doing
> the assignment first I'd really be very interested to learn something
new about uP
> architectures.

If you take a PowerPC, for example: A good compiler will translate c =
++a; into assembler instructions that are equivalent to "c = a + 1; a = a
+ 1; " and not "a = a + 1; c = a; ".

The PowerPC has no "move register" instruction. It only has an instruction
"register1 = register2 + constant" and you can pick a constant of 0 to get
a "move register". If a PowerPC needs the old value of a, it just
calculates new value - 1 at no extra cost.
--



Sat, 26 Jul 2003 05:03:30 GMT  
 Sequence point question (function result semantics)

Quote:


> > I suppose that since C was developed to be easy for compiler writers
> > the obvious solution is to write my own compiler that does the
> > logical thing with c = f(x)++.

> What on earth might the "logical thing" be?

> > I'm certainly glad that logic wasn't a deciding factor in writing the
> > C standard!

> It was.  You should try it before you knock it.

OK, since you've been following this thread so closely, you should be able
to tell me what I think the logical thing is.  OTOH, (apologies to our
regular listening audience) I think the logical thing is that, as with c =
x++;  c gets assigned the value of f(x).  f(x) is incremented but since it
cannot be used henceforth, the incrementation is optimized away.  If you
find this illogical, then I'm probably correct in assuming you were on the
standards committee.

Logic was not the deciding factor in the C standard.  The biggest factor,
as far as I can find is to not make 'incorrect' any previously existing C
code.  Dennis Ritchie himself has admitted as much - certainly in relation
to the relative precedence of &, ==, and &&.  If you want to argue the
point with Mr. Ritchie, please don't let me stand in your way - I'd just
like an audio tape for the laughs.

--Jeff Turner
--



Wed, 30 Jul 2003 17:29:33 GMT  
 
 [ 38 post ]  Go to page: [1] [2] [3]

 Relevant Pages 
 

 
Powered by phpBB® Forum Software