为什么静态局部变量在这种情况下不保留它的值?
why static local variable doesn't preserve it's value in this case?
先来看看:
#include <stdio.h>
static int v1 = 0;
int fun()
{
static int v2 = 0;
++v2 && ++v1;
printf("%i\n", v2);
return v2;
}
int main()
{
++v1;
printf("%i\n", fun());
printf("%i\n", v1);
}
输出:
1
1
2
所以整个事情都是关于 C 中的全局静态和局部静态变量,所以静态变量的主要 属性 是它“保留它的值”这一事实,但在这里它不是,第一条输出符合预期: fun()
中 v2
的值应该是 ++v2
,即 1
但第二条不是,预期的是当它调用时main()
它的保留值将是 1
并且它会再次 ++v2
所以第二个输出预计是 2
。
当我们消除 return v2
时,程序会按预期工作。
#include <stdio.h>
static int v1 = 0;
int fun()
{
static int v2 = 0;
++v2 && ++v1;
printf("%i\n", v2);
}
int main()
{
++v1;
printf("%i\n", fun());
printf("%i\n", v1);
}
输出:
1
2
2
问题是为什么?谢谢。
main()
递增v1
,所以它的值为1
.
当您调用 fun()
时,它会递增 v2
和 v1
,因此 v2
是 1
而 v1
是 2
.
然后它打印 v2
,所以它打印 1
。这是第一行输出。
然后它 returns v2
, 所以它 returns 1
.
然后 main()
打印 return 值,所以它打印 1
。这是第二行输出。
然后 main()
打印 v1
,所以它打印 2
。这是第三行输出。
您没有调用 fun()
两次,因此您的代码段中的任何内容都取决于该值是否保留。为了看到变量被保留,您必须再次调用该函数。如果再添加一个
printf("%d\n", fun());
最后它会打印两次2
,因为v2
的值会被保留和递增。
你的第二个代码片段产生了未定义的行为,因为声明给 return 和 int
的函数没有 return 任何东西。它只是不小心 return 达到了您的预期——2
是 printf()
的 return 值,因为它 return 是它打印的字符数( 1
后跟一个换行符),它被留在用于函数的 return 值的位置。改函数做
printf("|%d|"\n", v2);
我希望你会得到不同的结果。
带有 return 语句的第一个代码块是正确的行为。
程序的流程是这样的:
- 编译器从main()开始
- v1 = v1 + 1;因此 v1 = 1
- 您正在 print 语句中调用 fun() --> 程序控制转到 fun():
- v2 已初始化
- v1和v2递增,v2 = 1; v1 = 2; (如果 && 语句中的第一个值结果为 0,这部分实际上很棘手)
- 向控制台打印 1
- returns 调用函数的 v2 的值为 1 的值;在这种情况下 main()
- 控制权又回到了主线;由于您正在打印它打印的函数的 return 值 1
- 最后一条语句打印出 v1 的值为 2。
因此输出为
1
1
2
在第二个代码块中,您可能刚刚走运。函数签名说它 return 是一个 int 而你 return 什么都没有。这会导致 erratic/undefined 行为。不幸的是,C 作为一种语言并没有对程序员强制执行此操作。
有关由于 eax 寄存器 导致的这种未定义行为的原因的更多详细信息,请参阅:Function returns value without return statement
先来看看:
#include <stdio.h>
static int v1 = 0;
int fun()
{
static int v2 = 0;
++v2 && ++v1;
printf("%i\n", v2);
return v2;
}
int main()
{
++v1;
printf("%i\n", fun());
printf("%i\n", v1);
}
输出:
1
1
2
所以整个事情都是关于 C 中的全局静态和局部静态变量,所以静态变量的主要 属性 是它“保留它的值”这一事实,但在这里它不是,第一条输出符合预期: fun()
中 v2
的值应该是 ++v2
,即 1
但第二条不是,预期的是当它调用时main()
它的保留值将是 1
并且它会再次 ++v2
所以第二个输出预计是 2
。
当我们消除 return v2
时,程序会按预期工作。
#include <stdio.h>
static int v1 = 0;
int fun()
{
static int v2 = 0;
++v2 && ++v1;
printf("%i\n", v2);
}
int main()
{
++v1;
printf("%i\n", fun());
printf("%i\n", v1);
}
输出:
1
2
2
问题是为什么?谢谢。
main()
递增v1
,所以它的值为1
.
当您调用 fun()
时,它会递增 v2
和 v1
,因此 v2
是 1
而 v1
是 2
.
然后它打印 v2
,所以它打印 1
。这是第一行输出。
然后它 returns v2
, 所以它 returns 1
.
然后 main()
打印 return 值,所以它打印 1
。这是第二行输出。
然后 main()
打印 v1
,所以它打印 2
。这是第三行输出。
您没有调用 fun()
两次,因此您的代码段中的任何内容都取决于该值是否保留。为了看到变量被保留,您必须再次调用该函数。如果再添加一个
printf("%d\n", fun());
最后它会打印两次2
,因为v2
的值会被保留和递增。
你的第二个代码片段产生了未定义的行为,因为声明给 return 和 int
的函数没有 return 任何东西。它只是不小心 return 达到了您的预期——2
是 printf()
的 return 值,因为它 return 是它打印的字符数( 1
后跟一个换行符),它被留在用于函数的 return 值的位置。改函数做
printf("|%d|"\n", v2);
我希望你会得到不同的结果。
带有 return 语句的第一个代码块是正确的行为。 程序的流程是这样的:
- 编译器从main()开始
- v1 = v1 + 1;因此 v1 = 1
- 您正在 print 语句中调用 fun() --> 程序控制转到 fun():
- v2 已初始化
- v1和v2递增,v2 = 1; v1 = 2; (如果 && 语句中的第一个值结果为 0,这部分实际上很棘手)
- 向控制台打印 1
- returns 调用函数的 v2 的值为 1 的值;在这种情况下 main()
- 控制权又回到了主线;由于您正在打印它打印的函数的 return 值 1
- 最后一条语句打印出 v1 的值为 2。
因此输出为
1
1
2
在第二个代码块中,您可能刚刚走运。函数签名说它 return 是一个 int 而你 return 什么都没有。这会导致 erratic/undefined 行为。不幸的是,C 作为一种语言并没有对程序员强制执行此操作。
有关由于 eax 寄存器 导致的这种未定义行为的原因的更多详细信息,请参阅:Function returns value without return statement