c - “静态”关键字如何影响计算?
问题描述
我在这段代码中有一个问题,使用static
关键字。这里,在n = 3之后,我以为r
是5,结果发现r
是50!我不知道static
这里是如何工作的:
int magic(int n)
{
static int r = 5;
if (n <= 0) return 10;
if (n > 3)
{
r = 50;
return(r + magic(n-1));
}
return(r - magic(n-1));
}
int main()
{
int x;
x = magic(8);
printf("%d",x);
}
这里的输出是 290,因为r
在所有情况下的值都是 50。请有人可以帮助我。
解决方案
当您有语句时static int r = 5;
,这会向编译器发出信号,表明该变量r
将5
在编译时初始化为该值。这意味着,它不会5
在每次调用该函数时重置!
此外,该行if (r > 3)
无法按照您的建议工作(请参阅我在您的问题中的评论)!改成按if (n > 3)
你说的做。
无论如何,下面的代码做了一些不同的事情(输出 245),但我不确定你期望输出是什么:
#include <stdio.h>
int magic(int n)
{
int r = 5; // NOT STATIC - so this is reset to 5 at the start of each call!
if (n <= 0) return 10;
else if (n > 3) { // Your "if (r > 3)" means the block will ALWAYS execute!
r = 50;
return(r + magic(n - 1));
}
return(r - magic(n - 1));
}
编辑:我将尝试添加一些说明!考虑一个声明和初始化“全局”范围内的静态变量的语句(即不在任何函数内,甚至不在main
):
static int StatInt1 = 42;
当编译器遇到此语句时,它会为程序“分配”一部分内存,大到足以容纳 a int
,并为那块内存赋予表示 的值42
。编译器不会生成任何机器代码指令来将给定的值移动到该内存中;事实上,它不可能生成这样的代码——因为没有运行该代码的“上下文”。
但是,如果您稍后(在某个函数中或在 中main
)有这样的语句:
StatInt1 = 9;
然后编译器将生成代码,将值的表示移动9
到先前为变量“分配”的内存中。这段代码的确切内容取决于编译器和目标机器,但假设它是一条指令MOVE 9 TO @StatInt1
(其中@StatInt1 是“已分配”内存块的地址)。
现在,如果您要将static int StatInt1 = 42;
语句移动到函数体中(就像您所做的那样),这(根据定义)不会改变编译器解释语句的方式!它所做的只是访问该函数的变量“本地”。仍然没有生成代码来将值移动到变量中!
但是函数中未声明为静态的变量的处理方式非常不同 - 我们有时将此类变量称为“自动”!此类变量的内存块仅在实际调用函数时才“分配”,然后每次调用函数时都会为其分配初始化程序中给出的值。(通常,大多数编译器会在堆栈上创建内存:函数结束时“清除”的短期内存。)
在您的代码中,static int r = 5;
不会生成任何代码,因此在5
调用函数时不会“自动”重新分配值。50
因此,一旦以将值分配给的方式调用该函数r
,它将保留该值,直到您显式地给它另一个值。
如果这是漫无边际的,我深表歉意 - 但我希望它能让你清楚(呃)发生了什么!
推荐阅读
- fastapi - 使用 fastAPI 提供文件的问题
- javascript - 节点js和reactJS的“无法发布错误”
- sql-server - SQL Server 触发器:如何将空格分隔的文本分解为电子邮件列表
- javascript - 为什么点击音量调低按钮正确减小而音量调高按钮增加到最大值
- f# - 使用 Moq 如何访问返回的显式类型的属性
- common-lisp - 使用 ~/quicklisp/local-projects 中的包,它使用 asdf:require-system 而不是 ql:quickload 加载
- r - 每次向量中的项目与某个类别相关时,我可以使用 R 获取类别计数吗?
- android - 在 Android 手机上运行应用程序时出现此错误
- react-native - 当变换缩放反应本机时,动画视图是锯齿状的
- vba - 当某个日期大于或等于另一个日期时,如何创建弹出消息?