我发现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
谢谢!
答案 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是程序及其存储值的完整执行 在程序启动之前只初始化一次。
-
初始化程序中具有静态或。的对象的所有表达式 线程存储持续时间应为常量表达式或字符串 文字。