这里我有一个名为max(a,b)
的函数来获取两个中的最大数。
我发现使用a
的变量b
和printf()
的值在执行后会有所不同
printf("maxab()=%d after max: a=%d b=%d \n",max(a++,b++),a,b);
当a
和b
为Global variables
和Local variables
时。以下是我的代码:
#include<stdio.h>
int max(int a,int b)
{
if(a>b)
{
//printf("In func max():%d %d \n",a,b);
return a;
}
else {
//printf("In func max():%d %d \n",a,b);
return b;
}
}
void jubu_test(void)
{
int a=1;
int b=2;
printf("maxab()=%d after max: a=%d b=%d \n",max(a++,b++),a,b); //a=2,b=3
}
int c=2;
int d=1;
void quanju_test(void)
{
printf("maxcd()=%d c=%d d=%d \n",max(c++,d++),c,d); //c=2,d=1
c=2;
d=1;
int f=max(c++,d++);
printf("maxcd()=%d after max: c=%d d=%d \n",f,c,d); //c=3,d=2
}
int main(int argc, char** argv)
{
jubu_test();
quanju_test();
}
我在计算机上得到的结果是:
maxab()=2 after max: a=2 b=3
maxcd()=2 c=2 d=1
maxcd()=2 after max: c=3 d=2
我的问题是:为什么在第二个输出中a和b是它们的原始值以及为什么第三个输出是+ 1和b + 1?为什么当a和b是全局变量时,打印出的a和b的值只会在我们首先执行max(a++,b++)
时发生变化?为什么a和b是局部变量并不重要?
谢谢! (在Windows 10上使用gcc 5.3.0)
答案 0 :(得分:5)
根据Why are these constructs (using ++) undefined behavior?,表达式printf(... max(a++,b++),a,b);
是未定义的行为。
a++
的评估与a
的评估无关,b++
和b
的评估相同。在调用函数之前有一个序列点并不重要,因为可以在此之前以任何顺序评估子表达式。
未定义的行为=总是一个错误。意味着该程序可以有任何行为,打印任何东西,崩溃&amp;烧伤等。
它是未定义行为的原因是,C11 6.5 / 2:
如果标量对象的副作用相对于其中任何一个都没有排序 对同一个标量对象或值有不同的副作用 使用相同标量对象的值进行计算,行为是 未定义。
(a
是一个标量对象 - 不是数组或结构等。a++
会导致更新变量的副作用。这与{{1}的值计算无关在同一个表达式的其他地方。)
不要与未指明的行为混淆,这意味着程序将具有确定性,但您无法知道以哪种方式。例如,函数参数的评估顺序是未指定的行为:
a
这可能会打印int func (void)
{
static int x=0;
x++;
return x;
}
printf("%d %d", func(), func());
或1 2
,我们无法知道或假设哪个适用。编译器不需要记录这一点,也不必在整个程序中表现一致。它可以在一个案例中选择一个订单,在另一个案例中选择另一个订单。
依赖于未指定行为的代码很糟糕,但不会像包含未定义行为的代码那样完全不正常。
答案 1 :(得分:3)
我相信,它与变量的范围无关。 C没有指定函数参数求值的确切顺序。所以,这是未指明的行为。