C - 为什么我的变量没有被破坏?

时间:2017-07-31 17:52:18

标签: c static

我发现C语言(我来自javascript),我有这种简单的脚本

#include "stdio.h"

int rand(){
  int numb;
  for (int i = 0; i < 4; ++i)
  {
    numb++;
  }
  return numb;
}

int main(int argc, char const *argv[])
{
  int a = rand();
  int b = rand();
  printf("%i , %i\n", a, b);
  return 0;
}

我的问题是为什么我获得相同的结果(4,8),好像变量被声明为静态&amp;初始化为0?

static int numb = 0;

我不太确定能够很好地理解变量的范围:s

谢谢!

4 个答案:

答案 0 :(得分:4)

程序具有未定义的行为,因为局部变量numb未初始化,并且通常具有不确定的值。

您的结果将通过以下方式解释。似乎第一次调用该函数时,为变量分配的内存存储为零。

当第二次调用函数时,函数对具有自动存储持续时间的变量使用相同的内存,但通常不必使用相同的变量地址。

根据C标准(6.2.4对象的存储持续时间)

  

1对象具有确定其生命周期的存储持续时间。那里   有四个存储持续时间:静态,线程,自动和   分配...

  

6对于没有可变长度数组类型的对象,   它的生命周期从进入到它所在的区块延伸   关联,直到该块的执行以任何方式结束。 (进入   封闭块或调用函数暂停,但不结束,   执行当前块。)如果以递归方式输入块,   每次都会创建一个新的对象实例。初始值   对象是不确定的。如果指定了初始化   对象,每次声明或复合时执行   在块的执行中达到了字面值; 否则,   每次达到声明时,价值就会变得不确定

最后(J.2未定义的行为)

  

- 使用具有自动存储持续时间的对象的值   它是不确定的(6.2.4,6.7.9,6.8)。

答案 1 :(得分:0)

  

我的问题是为什么我得到了相同的结果(4,8),好像是   声明为静态和变量的变量初始化为0?

这是未定义的行为(UB)。你的观察仅仅是巧合。使用其他编译器或不同的架构进行编译,结果可能会有所不同。

您必须自己初始化函数中的整数。

答案 2 :(得分:0)

当您调用rand()时,numb变量将在数据堆栈上分配,并且堆栈指针会增加。

当函数结束并返回main时,释放分配的数据堆栈,并减少堆栈指针(实际内存中的值保持不变)。

当您回想起rand()时,numb变量将再次分配到数据堆栈的先前位置。它没有初始化,所以之前的值仍然存在......

答案 3 :(得分:-2)

对于downvoters:它都符合C标准。

3种不同的案例

1.未定义的行为

int foo(){
  int numb;
  for (int i = 0; i < 4; ++i)
  {
    numb++;
  }
  return numb;
}

UB - 无需解释。任何事情都可能发生

2.Automatic initialised variable

int foo(){
  int numb = 0;
  for (int i = 0; i < 4; ++i)
  {
    numb++;
  }
  return numb;
}
每次调用函数时,

numb都会初始化为零,并在退出时销毁。

3.静态初始化变量

int foo(){
  static int numb = 0;
  for (int i = 0; i < 4; ++i)
  {
    numb++;
  }
  return numb;
}

变量只初始化一次并保持其值。静态自动变量的范围与自动变量的范围相同,即它是定义它的块的本地 - 在本例中是函数foo,但是在程序生命周期中保留该值。这些变量只初始化一次,并在调用之间保持它们的值。如果静态自动变量未初始化 - 它将在启动过程中初始化为默认值 - 这是实现定义的(执行初始值)(通常是.bss段并初始化为零)。

来源:C标准

  

应初始化具有静态存储持续时间的所有对象(设置为   程序启动前的初始值。的方式和时间   否则这种初始化是未指定的。

-

  

在没有存储类的情况下声明其标识符的对象   符   _Thread_local,无论是使用外部链接还是内部链接,还是使用存储类说明符static,都具有静态存储持续时间。它的   lifetime是程序及其存储值的完整执行   在程序启动之前只初始化一次。

-

  

初始化程序中具有静态或。的对象的所有表达式   线程存储持续时间应为常量表达式或字符串   文字。