C 局部静态变量在方法中是如何工作的?

C 局部静态变量在方法中是如何工作的?,c,function,static,C,Function,Static,下面是我的代码: //main.c int f() { static int x = 0; x += 1; return x; } int main() { f(); printf("%d", f()); } 输出为2 我知道静态变量将保持状态,但由于我调用了两次f(),每次x都首先设置为0(static int x=0;),然后加上1,那么输出应该是1,无论我调用f()多少次?您对f()进行了两次调用,x具有静态存储持续时间,其生存

下面是我的代码:

//main.c

int f()
{
    static int x = 0;
    x += 1;
    return x;
}

int main()
{
   f();
   printf("%d", f());
}
输出为
2


我知道静态变量将保持状态,但由于我调用了两次
f()
,每次
x
都首先设置为0(
static int x=0;
),然后加上1,那么输出应该是
1
,无论我调用
f()
多少次?

您对
f()
进行了两次调用,x具有静态存储持续时间,其生存期是程序的整个执行过程。这就是为什么打印2而不是1。

静态
变量不仅持续存在,而且只初始化一次,因此
x
不是“每次先设置为0”,它在第二次调用中保持
1
,然后递增。的确如此

static int x = 0;  // x is initialized once only

static int x;
x = 0; // x is set to 0 with every call
每次x设置为0时

不,您正在错误地读取代码。这里的
=
并不表示赋值,而是表示初始化,因为它是声明的一部分。变量的初始值显式指定为0。静态变量在程序执行期间只初始化一次。如果它们的声明出现在函数中,则不会改变该行为

此外,静态变量的初始值设定项必须是常量表达式(可以在编译时计算为已知值的表达式)。这意味着实际上,实现不需要引入代码来在函数内部进行任何初始化。该值可以在程序启动时简单地加载到变量的存储器中

“…但是由于我调用了
f()
两次,每次
x
都设置为
0
第一次(
static int x=0;
),”

否。
x
未在每次调用
f
时设置为
0


静态
变量仅在第一次调用定义它们的函数时初始化一次

与automatic变量相比,特殊之处在于分配的内存对象一直持续到程序结束

在对函数
f
的不同调用之间,
x
的对象和值保持不变。因此,
x
在每次调用函数时递增一,而不重置为一次初始化的值

// Calls to f() in order
f();         // value of x at the end of the function: 1
f();         // value of x at the end of the function: 2
f();         // value of x at the end of the function: 3
f();         // value of x at the end of the function: 4
// and so on.
因此,当您两次调用
f()
时,
2
是函数返回时
x
的正确值


旁注:

  • 0
    的显式初始化是多余的<默认情况下,代码>静态变量初始化为
    0

  • 不应忽略C中函数的参数列表定义/声明。不要写
    intf()
    ,而是写
    intf(void)
    int main()
    也应编辑为
    int main(void)
    int main()
    已过时

静态变量也可以在局部范围内声明<代码>静态持续时间表示在程序启动时分配对象或变量,在程序结束时取消分配对象或变量。()

因此,这对于示例程序意味着
2
是正确的:

下面的示例代码以及顶部的语句说明了原因:

首次通话:

static int x = 0;  // unlike non-static variables, initialization is executed 
                   // only once on 1st call to function.
                   // Also unlike non-static, local variables, locally created static 
                   // variables are initialized to 0 automatically  
                   // making the explicit assignment to 0 unnecessary. 
                   // (although still a good habit. :)) 
...
x++; //x==1
第二次电话:

static x = 0 //skipped 
...
x++; //x==2
第三个电话:

static x = 0 //skipped 
...
x++; //x==3
等等,直到节目结束


(已替换<代码> x+=1;< /代码>以其惯用的快捷方式:<代码> x++;< /代码>

回答之前:考虑到这个问题已经有8个答案,话题相当基本。您的答案是否添加了一些新的内容,或者以显著的方式改进了一些已经说过的内容?使用
intmain(void)
表示法很好,但是请注意C11标准(中的示例3)显示了
intmain(){…}
。诚然,它不是规范性的,因为它是一个例子,但…@JonathanLeffler是的,我知道。我也发现了这些例子,并对此感到好奇。我对这个案例进行了讨论,结论是更好地使用
intmain(void)
表单。因此,我提出建议。我100%同意“更好”。我在警告“符合标准”。它是合规的代码,但并不能打败现代实践。@JonathanLeffler如何看待Keith关于保证符合未来标准的推理(以防委员会消除这种歧义)?毫无疑问,使用显式
int main(void)
形式更好-但目前,
int main()
表单也符合标准,即使不是首选符号。类似的注释适用于函数定义的非原型样式。旧风格仍然符合标准;它根本不应该被使用。当您重新编写答案(使用“is Observe”)时,这涉及到我的诡辩(这是小规模的诡辩,不是如何编写好的C代码的哲学中的主要练习),所以一切都很好,尽管我会使用“Observe”而不是“Observe”。