C中的评估顺序,带有一个变量,该变量具有改变同一赋值中的变量的函数

时间:2014-11-25 04:06:17

标签: c reference unspecified-behavior

所以要预先做好,这与我需要指导的家庭作业有关。我不需要代码或任何东西,但这让我发疯,我需要一些澄清。我甚至不在书中提问。

我有以下代码:

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);
}

当我运行它时,我得到“a的值为20”和“右边的函数调用,40”和“左边的函数调用,40”。

我感到困惑的是,我之前有一个非常相似的问题

#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);
}

sum1的答案为46,sum2的答案为48,在我的脑海中,在codepad.org的编译器中从左到右的评估是有意义的。但是在Pelles C编译器中它出现了48.你可以看到第一个问题的代码几乎完全相同。

我确实找到了这个链接:Parameter evaluation order before a function calling in C这似乎解释了这种不一致性,但我想确保我的思路并没有偏离。那么可以肯定地说它取决于编译器以及编译器认为最有效的东西吗?

1 个答案:

答案 0 :(得分:2)

在这两个表达中

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

您有未指定的行为,因为+的子表达式的评估顺序未指定。在调用之后,编译器可以在之前评估(i/2)(j/2),因为它认为合适。

&&||运算符不同,它强制在左侧评估左侧,+-*,{{1} },/和所有按位运算符允许编译器根据其优化策略选择最方便的评估顺序。这意味着不同的编译器可能决定以不同的方式评估%的边。

从实际角度来看,这意味着你应该在同一个表达式中使用副作用不超过一次的表达式。您可以重写两个表达式以强制执行所需的评估顺序,例如

+

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