C语言中的求值顺序,用一个函数指定一个变量,该函数在同一赋值中改变一个变量

C语言中的求值顺序,用一个函数指定一个变量,该函数在同一赋值中改变一个变量,c,reference,unspecified-behavior,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, "); pri

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

我有以下代码:

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);
}
#包括
int fun(int*k){
*k+=4;
返回3*(*k)-1;
}
void main(){
int i=10,j=10,sum1,sum2;
sum1=(i/2)+乐趣(&i);
sum2=乐趣(&j)+(j/2);
printf(“%d”,sum1);
}
对于sum1,答案是46,对于sum2,答案是48,在我看来,在codepad.org的编译器中,从左到右的计算是有意义的。但在Pelles C编译器中,结果是48。您可以看到,第一个问题中的代码布局几乎完全相同


我确实找到了这个链接:这似乎解释了这种不一致性,但我想确保我的思路没有偏离。那么,可以安全地说,它取决于编译器,编译器认为什么是最有效的吗?

在这两个表达式中

sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);
您有未指定的行为,因为
+
的子表达式的求值顺序未指定。编译器可以在调用之前或之后自由地计算
(i/2)
(j/2)
,视情况而定

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

从实用的角度来看,这意味着您应该在同一个表达式中最多使用一次具有副作用的表达式。例如,您可以重写这两个表达式以强制执行所需的求值顺序

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


了解。例如,表达式
a+fun(&a)
中没有序列点,因此编译器可以自由地首先计算
a
fun(&a)
。您有未定义的行为这基本上是您链接的问题的重复,此问题的答案是相同的。我对这个问题的回答基本上是对你链接的问题的重复。@Gopi:未指定,不是未定义。另一个问题类似,但不一样,所以我想确保在用函数和参数评估这个问题时,我没有遗漏一些基本概念。好的,实际上,我在做这件事的时候,一直在努力强迫表达式按照你提到的方式进行计算。这让我有点震惊,像这样的东西可能是未定义的,我认为我遗漏了一些重要的基本概念。@NationalGrammarodeo我认为这是一个哲学上的决定:强制任何特定的求值顺序都会限制编译器设计人员使用特定的策略,可能会干扰性能。另一方面,标准的设计者试图避免任何会降低性能的事情,有时会以混淆行为为代价。你发现了一个很好的例子,说明了未指定的顺序会很快让人困惑。嗨,我遇到了一个类似的问题,但是我和另一个回答者不同意这种行为,如果它是未定义或未指定的。如果你感兴趣并且有时间,请检查这个问题:我很想听听你的意见。@2501我认为你是对的,内部的副作用
fun
使得这个问题没有定义,而不仅仅是未指定。谢谢@达斯宾莱特?事实上,我认为结果是未指定的,行为是有定义的。函数内部由两个序列点包围的赋值。
sum2 = sun(&j);
sum2 += j/2;