order of evaluation in C with assigning a variable with a function that changes a variable in the same assignment

432 views Asked by At

So to be up front, this is related to a homework assignment that I need guidance with. I don't need code or anything, but this is driving me crazy and I need some clarification. I'm not even asking the question in the book.

I have the following code:

int fun(int *c){
*c += 10;
return *c ;
}

void main(){

int a, b;
a = 10;
b = a + fun(&a);
printf("value of a is %d\n", a);
printf("With the function call on the right, ");
printf(" b is: %d\n", b);
a = 10;
b = fun(&a) + a;
printf("With the function call on the left, ");
printf(" b is: %d\n", b);
}

When I run it, I get "value of a is 20" and "with the function call on the right, 40" and "with the function call on the left, 40".

What I am confused about is that I had a very similar question right before

#include<stdio.h>

int fun(int *k) {
*k += 4;
return 3 * (*k) - 1;
}

void main() {
int i = 10, j = 10, sum1, sum2;
sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);

printf("%d", sum1);
}

And the answer comes out to 46 for sum1 and 48 for sum2 which in my head makes sense with left to right evaluation in codepad.org's compiler. But in Pelles C compiler it comes out to 48. You can see that the code from the first problem is laid out pretty much exactly the same.

I did find this link: Parameter evaluation order before a function calling in C which seems to explain this inconsistency but I want to make sure I'm not way off in my line of thinking. So would it be safe to say that it depends on the compiler and what the compiler feels is most efficient?

1

There are 1 answers

10
Sergey Kalinichenko On BEST ANSWER

In both these expressions

sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);

you have unspecified behavior, because the order of evaluation of the subexpressions of + is unspecified. The compiler is free to evaluate (i/2) and (j/2) before or after the call, as it sees fit.

Unlike && and || operators that force evaluation of their left side before their right side, +, -, *, /, %, and all the bitwise operators allow the compiler to pick the most convenient order of evaluation, depending on its optimization strategy. This means that different compilers may decide to evaluate the sides of + differently.

What this means from the practical perspective is that you should use expressions with side effects no more than once in the same expression. You can rewrite both your expressions to force the order of evaluation that you want, for example

sum1 = i/2;
sum1 += fun(&i);

or

sum2 = sun(&j);
sum2 += j/2;