2

因此,首先,这与我需要指导的家庭作业有关。我不需要代码或任何东西,但这让我发疯,我需要澄清一下。我什至没有问书中的问题。

我有以下代码:

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。您可以看到第一个问题的代码布局几乎完全相同。

我确实找到了这个链接:在 C 中调用函数之前的参数评估顺序,这似乎可以解释这种不一致,但我想确保我的思路没有偏离。那么可以肯定地说它取决于编译器以及编译器认为最有效的方式吗?

4

1 回答 1

2

在这两种表达方式中

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

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

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

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

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

或者

sum2 = sun(&j);
sum2 += j/2;
于 2014-11-25T04:18:23.123 回答