(C question) (s - out.s) + func(&out) -> ?

D. Hugh Redelmeier hugh-pmF8o41NoarQT0dZR+AlfA at public.gmane.org
Wed Nov 6 20:20:53 UTC 2013


| From: William Park <opengeometry-FFYn/CNdgSA at public.gmane.org>

| On Tue, Nov 05, 2013 at 01:06:39PM -0500, Lennart Sorensen wrote:
| > Functions calls are evaluated before addition/subtraction.  That's in
| > the standard.  Since the function modifies the parameter, the value
| > changes before the addition work is done.

Lennart isn't accurate here.

For example, in f(a+3), the function call is evaluated after addition.


| Multiplication has higher precedence than addition.  I'm not talking
| about that.  It's just that gcc removed parenthesis.  Eg.
|     (a + b) + c
| gcc can rewrite it to
|     a + (b + c)
| even though I explicitly said do "a+b" first.

"do first" is not what we need to talk about.

And that example isn't at all like the one you had problems with.

The steps needed to evalutate an expression in math are simple: there
are no side effects.  Not so in C.

(Oh, and ordinary math operations have associativity, commutativity
and other properties that don't always carry over into C.  But that is
a different topic.)

"(a + b) + c" has no obvious side effect, so that isn't an example of
your original problem

Let's go back to your original problem.
        s = (s - out.s) + func (&out);
        where 'out' is changed inside function 'func'.
This one has obvious side effects, so we can get concrete about it.

1:        (s - out.s)
2:        func(&out)
3:        s = (1) + (2)

We know that 3 must be evaluated (computed) after 1 and 2.

There is nothing to say the order of evaluation of 1 vs the evaluation
of 2.

In C:
- 1 could be evaluated before 2
- 1 could be evaluated after 2
- 1 could be evaluated at the same time as 2
You, the programmer, just don't know which.

Furthermore, when they are evaluated at the same time, there is NO
promise of what happens.  None.  Like: the result could be a crash.
Or worse: continuing with the state completely curdled.

Those bizarre results are not normal on current hardware because it
would take more work to produce them, not less.  But as parallelism
increases, there is more chance of getting surprising results.

But it is easy to solve your problem.  You gave an outline:

Original code:
    char *s;
    struct { char *s; } out;
    char *func();

    s = (s - out.s) + func (&out);

Outline:
    What I want is 
        - to calculate (s - out.s) first, then 
        - add that difference to pointer returning from func().
    Here, order is important, because func() changes 'out'.

So do that:
    char *s;
    struct { char *s; } out;
    char *func();

    {
         char *t = s - out.s;

         s = t + func (&out);
    }

What you want is clearly and precisely exressed in this code.

I consider it bad style to have side-effects within expressions that
are not at the top level.  It makes the code harder to understand.
Your code is an illustrative example.  But C makes it convenient.
--
The Toronto Linux Users Group.      Meetings: http://gtalug.org/
TLUG requests: Linux topics, No HTML, wrap text below 80 columns
How to UNSUBSCRIBE: http://gtalug.org/wiki/Mailing_lists





More information about the Legacy mailing list