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

Lennart Sorensen lsorense-1wCw9BSqJbv44Nm34jS7GywD8/FfD2ys at public.gmane.org
Wed Nov 6 20:39:00 UTC 2013


On Wed, Nov 06, 2013 at 03:20:53PM -0500, D. Hugh Redelmeier wrote:
> | 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.

Of course, since you have to evaluate the argument to pass to the
function.  x = y + f(a+3); would have to evaluate a+3 first, then f(the
result) then y + the result of the function.

Now if you go do things like:

x = y + f(y++);

then you can really get in trouble.  The compiler is not required to
store the result of y++ into y, before referencing it for the other y.
it just has to calculate the new value and pass it to the function and
at some point when it is convinient, store it to y.

> | 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.

I agree with that.

And people who think it runs faster if you put more stuff in one line
with more complexity are simply wrong.

-- 
Len Sorensen
--
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