c - C 中的求值顺序,通过使用在同一赋值中更改变量的函数来分配变量

标签 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这似乎解释了这种不一致,但我想确保我的思路没有偏离。那么可以肯定地说这取决于编译器以及编译器认为什么是最有效的吗?

最佳答案

在这两个表达式中

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;

关于c - C 中的求值顺序,通过使用在同一赋值中更改变量的函数来分配变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27118645/

相关文章:

c - malloc、calloc 和动态数组

c - 各种 glibc 和 Linux 内核版本兼容性

c - c文件中的linux命令行

c++ - 引用堆栈对象的地址

android - 来自 WeakGlobalRef 的 JNI LocalRef

c++ - 是否定义了 ofstream 实现的默认模式?

c - 为什么即使我没有返回对象,我的结构也会被清零?

c++ - 指向根的二叉树指针需要被引用和取消引用。为什么?

C++ cout 副作用排序

c - (x++, y) + (y++, x) 是未定义的还是未指定的,如果未指定,它可以计算什么?