c - 为什么全局变量与此函数中的局部变量不同?

标签 c scope function-call

这里我有一个名为 max(a,b) 的函数来获取两个中的最大值。 而且我发现执行printf()后变量ab的值是不一样的

printf("maxab()=%d after max: a=%d b=%d \n",max(a++,b++),a,b);

ab全局变量局部变量时。下面是我的代码:

#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是它们的原始值,为什么第三个输出是a+1和b+1?为什么a和b是全局变量,只有先执行max(a++,b++),打印出来的a和b的值才会改变?为什么当 a 和 b 是局部变量时无关紧要?

谢谢! (在 Windows 10 上使用 gcc 5.3.0)

最佳答案

根据 Why are these constructs (using ++) undefined behavior?,表达式 printf(... max(a++,b++),a,b);未定义行为.

a++ 的求值顺序与a 的求值无关,b++b 的求值顺序相同>。在调用函数之前有一个序列点并不重要,因为子表达式可以在此之前以任何顺序求值。

未定义的行为 = 总是一个错误。意味着该程序可以有任何类型的行为,打印任何内容,崩溃和烧毁等。

它是未定义行为的原因是这样的,C11 6.5/2:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

(a 是标量对象 - 不是数组或结构等。a++ 导致更新变量的副作用。这与值的关系是无序的a 在同一表达式中其他地方的计算。)


不要与未指定的行为 混淆,这意味着该程序将确定性地运行,但您无法知道以何种方式运行。例如,函数参数的求值顺序是未指定的行为:

int func (void)
{
  static int x=0;
  x++;
  return x;
}

printf("%d %d", func(), func());

这可能会打印 1 22 1,我们无法知道或假设哪个适用。编译器不需要对此进行记录,也不必在整个程序中保持一致。它可以在一种情况下选择一个订单,在另一种情况下选择另一个订单。

依赖未指定行为的代码是不好的,但不会像包含未定义行为的代码那样表现得完全不稳定。

关于c - 为什么全局变量与此函数中的局部变量不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43110588/

相关文章:

scala - Scala 中可以制作作用域计时器吗?

c - 在 ARM C 调用约定中要保存哪些寄存器?

c - 对于缓冲区溢出,使用pthreads时栈地址是多少?

c++ - 在 C/C++ (Linux)、LGPL 或 BSD 中确定 CPU 速度/内存是一项要求

c++ - 使用命名空间的区别 (std::vs::std::)

c++ - 在 Win32 环境下从 ntdll.dll 调用 Nt 函数,C++

java - 如何从存储在变量中的字符串调用 Java 函数

c++ - 在 yacc 文件中使用 C++ 代码

c - 我正在复习 c 是为了我自己的启发。此代码用于示例链接列表。我不明白指针逻辑

java - Java内部类的名称解析