将打印出什么? 6 6或6 7?为什么?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
答案 0 :(得分:150)
这里有两个问题,生命和范围。
变量的范围是可以看到变量名称的位置。这里,x只在函数foo()中可见。
变量的生命周期是它存在的时间段。如果在没有关键字static的情况下定义x,则生命周期将从foo()的入口到foo()的返回;所以每次通话都会重新初始化为5。
关键字static用于将变量的生命周期延长到程序的生命周期;例如初始化只发生一次,然后变量保留其值 - 无论它是什么 - 将来所有对foo()的调用。
答案 1 :(得分:41)
输出: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;
}
答案 2 :(得分:9)
6 7
编译器安排每次输入函数时都不会发生静态变量初始化
答案 3 :(得分:9)
这与具有以下程序相同:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
静态关键字在该程序中所做的全部是它告诉编译器(基本上)'嘿,我在这里有一个变量,我不希望任何其他人访问,不要告诉其他人它存在'。
在一个方法中,static关键字告诉编译器与上面相同,但是,“不要告诉任何人这个函数以外的存在,它应该只能在这个函数内部访问”。
我希望这会有所帮助
答案 4 :(得分:5)
只要程序运行,函数内的静态变量就会有生命周期。每次调用函数时都不会分配它,并在函数返回时取消分配。
答案 5 :(得分:2)
输出为6 7
。在该转换单元中的任何函数执行之前,静态变量(无论是否在函数内部)仅被初始化一次。之后,它会保留其值直到修改。
答案 6 :(得分:2)
Vadiklk,
为什么......?原因是静态变量只初始化一次,并在整个程序中保持其值。 意思是,你可以在函数调用之间使用静态变量。 它也可用于计算“调用函数的次数”
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部分。
反过来,Auto(本地)变量存储在Stack上,并且在调用函数时,所有堆栈上的变量都会重新初始化,因为为此创建了新的FAR(函数激活记录)。
为了更好理解,请在没有“静态”的情况下执行上述示例,并告诉您输出的内容。这让你理解这两者之间的区别。
由于 贾韦德
答案 7 :(得分:2)
x
的声明位于foo
内,但x=5
初始化发生在foo
之外!
我们需要了解的是
static int x = 5;
与
不同static int x;
x = 5;
其他答案使用了这里的重要词,范围和生命周期,并指出x
的范围是从函数foo
中的声明到函数结尾{ {1}}。例如,我通过将声明移动到函数的末尾来检查,这使得foo
在x
语句处未声明。
因此,语句的x++;
(范围)部分实际应用于您阅读它的地方,某处 INSIDE 该函数,并且仅从那里开始,而不是在函数内部。
然而,语句的static int x
(生命周期)部分是变量的初始化并且作为程序加载的一部分发生了函数的 OUTSIDE 。当程序加载时,变量x = 5
的值为x
。
我在其中一条评论中读到了这一点:" 此外,这并没有解决真正令人困惑的部分,这就是在后续调用中跳过初始值设定项的事实。 "所有电话都会被跳过。变量的初始化在函数代码之外。
理论上设置5的值,无论foo是否被调用,尽管如果你不在任何地方调用它,编译器可能会优化该函数。在调用foo之前,5的值应该在变量中。
在5
内,语句foo
根本不可能生成任何代码。
我发现地址static int x = 5;
在我将函数x
放入我的程序时使用,然后(正确)猜测如果我再次运行程序将使用相同的位置。下面的部分屏幕截图显示,即使在第一次调用foo
之前,x
的值仍为5
。
答案 8 :(得分:1)
我们刚看完Wikipedia article on Static Variables ...
静态局部变量:在函数内声明为static的变量是静态分配的,同时具有与自动局部变量相同的作用域。因此,在一次调用期间函数放入其静态局部变量的任何值在再次调用函数时仍然存在。
答案 9 :(得分:1)
你会得到6 7,因为很容易测试,这就是原因:当第一次调用foo
时,静态变量x被初始化为5.然后它增加到6并打印。 / p>
现在接下来打电话给foo
。程序跳过静态变量初始化,而是使用最后一次分配给x的值6。执行正常进行,为您提供值7。
答案 10 :(得分:1)
6 7
x是一个仅从foo()可见的全局变量。 5是它的初始值,存储在代码的.data部分中。任何后续修改都会覆盖以前的值。函数体中没有生成赋值代码。
答案 11 :(得分:1)
6和7 因为静态变量只有一次初始化, 所以5 ++在第一次通话时变为6 第二次通话时6 ++变为7 注意 - 当第二次调用发生时,需要x值为6而不是5,因为x是静态变量。
答案 12 :(得分:0)
至少在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'时,则不需要这样做,并且可以使用编译器在输出汇编代码中存储的值在程序加载时初始化变量。