什么将被打印出来?6 6或6 7?又为什么呢
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
什么将被打印出来?6 6或6 7?又为什么呢
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Answers:
这里有两个问题,生存期和范围。
变量的范围是可以看到变量名称的位置。在这里,x仅在函数foo()中可见。
变量的生存期是变量存在的时间。如果x是在没有关键字static的情况下定义的,则生存期将是从foo()的条目到foo()的返回;因此每次调用都会将其重新初始化为5。
关键字static的作用是将变量的生存期延长到程序的生存期;例如,初始化仅发生一次,然后该变量将在以后对foo()的所有调用中保留其值-无论它变为何种值。
输出:6 7
原因:静态变量仅初始化一次(不同于自动变量),并且在运行时将忽略静态变量的进一步定义。如果未手动初始化,则将自动由值0初始化。所以,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
6 7
编译器安排每次输入函数时都不会发生静态变量初始化
与具有以下程序相同:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
static关键字在该程序中所做的全部工作是(实际上)告诉编译器“嘿,我在这里有一个变量,我不希望其他任何人访问,也不告诉其他任何人它存在”。
在方法内部,static关键字告诉编译器与上面相同,但是,“不要告诉任何人此函数存在于此函数之外,只能在此函数内部访问”。
我希望这有帮助
x
在main中进行戳戳和调整。这是全球性的。在原始示例中x
,本地是foo的唯一对象,只有在该块内才可见,这通常是可取的:如果foo存在以x
可预测和可见的方式进行维护,那么让其他人戳它通常是危险的。将其保留在范围内的另一个好处是foo()
它也保持foo()
可移植性。
c
,因此在这种情况下,您的示例在全球范围内都是非法的。(C需要用于全局变量的常量初始化器,C ++不需要)。
的声明在x
内部,foo
但是x=5
初始化在外部进行foo
!
我们在这里需要了解的是
static int x = 5;
与...不同
static int x;
x = 5;
其他答案在这里使用了重要的词,作用域和生存期,并指出的作用域x
从其在函数foo
中的声明到函数结束foo
。例如,我通过将声明移至函数末尾进行检查,从而使x
该x++;
声明未声明。
因此static int x
,该语句的(作用域)部分实际上适用于您在函数内部的某个地方阅读的地方,并且仅从那里开始,而不是函数内部的上方。
但是,x = 5
语句的(生命周期)部分是变量的初始化,并且作为程序加载的一部分发生在函数的OUTSIDE之外。变量x
带有5
程序加载时的值。
我在其中的一条评论中读到了这句话:“ 而且,这并没有解决真正令人困惑的部分,这是在后续调用中跳过初始化程序的事实。 ”在所有调用中都将跳过它。变量的初始化不在功能代码的范围内。
理论上,无论是否调用foo都将设置5的值,尽管如果您未在任何地方调用foo,编译器可能会对其进行优化。在调用foo之前,值5应该在变量中。
在的内部foo
,该语句static int x = 5;
根本不会生成任何代码。
x
当我将函数foo
放入我的程序时,我发现该地址使用了,然后(正确)猜测如果再次运行该程序将使用相同的位置。下面的部分屏幕截图显示了x
该值5
甚至在第一次调用之前就具有foo
。
输出将是6 7
。静态变量(无论是否在函数内部)在执行该转换单元中的任何函数之前仅初始化一次。之后,它将保留其值直到被修改。
瓦迪克
为什么...?原因是静态变量仅初始化一次,并在整个程序中保持其值。意味着,可以在函数调用之间使用静态变量。也可以用来计算“一个函数被调用了多少次”
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
答案是5 4 3 2 1,而不是您期望的5 5 5 5 5 5 ....(无限循环)。再次,原因是静态变量被初始化了一次,下次调用main()时,它不会被初始化为5,因为它已经在程序中初始化了。因此我们可以更改该值,但不能重新初始化。多数民众赞成在静态变量的工作原理。
或者,您也可以考虑按存储方式:将静态变量存储在程序的数据段中,并将存储在数据段中的变量初始化一次。并在初始化之前将它们保存在BSS部分中。
反过来,自动(本地)变量存储在堆栈中,并且在为此创建新的FAR(功能激活记录)时,始终将堆栈中的所有变量重新初始化。
可以,为了更好地理解,请在没有“ static”的情况下执行上述示例,并让您知道输出是什么。这使您了解这两者之间的区别。
谢谢贾维德
让我们看一下有关静态变量的Wikipedia文章 ...
静态局部变量:在函数内部声明为静态的变量被静态分配,同时具有与自动局部变量相同的作用域。因此,当再次调用该函数时,该函数在一次调用期间放入其静态局部变量的任何值仍将存在。
正如容易测试的那样,您将得到6 7的打印结果,原因如下:foo
第一次调用时,静态变量x初始化为5。然后将其递增到6并打印。
现在,下一个呼叫foo
。程序将跳过静态变量初始化,而是使用上次分配给x的值6。执行将正常进行,为您提供值7。
6和7因为静态变量仅初始化一次,所以5 ++在第一次调用时变成6,在第二次调用时6 ++变成7注意-当第二次调用发生时,因为x是静态变量,所以x的值是6而不是5。
至少在C ++ 11中,当用于初始化局部静态变量的表达式不是“ constexpr”(不能由编译器求值)时,则必须在首次调用该函数期间进行初始化。最简单的示例是直接使用参数初始化本地静态变量。因此,编译器必须发出代码以猜测该调用是否是第一个调用,而这又需要一个局部布尔变量。我已经编译了这样的示例,并通过查看汇编代码来检查这是否正确。这个例子可以像这样:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
当然,当表达式为'constexpr'时,则不需要这样做,并且可以使用编译器在输出汇编代码中存储的值在程序加载时初始化变量。