【问题标题】:Automatic variable has static lifespan if not initialized?如果未初始化,自动变量是否具有静态寿命?
【发布时间】:2013-05-10 10:04:47
【问题描述】:

我很好地理解了静态局部变量的概念:全局寿命,局部作用域。同样,我理解自动变量会在程序流进入和离开变量的上下文时自动分配/解除分配。

#include <stdio.h>

void test_var(void){
    static unsigned foo = 0;
    unsigned bar = 0;
    printf(" %u   %u\n", foo++, bar++);
}

int main(void){
    printf("Foo Bar\n");
    printf("--- ---\n");
    for(unsigned x = 0; x < 10; x++){
        test_var();
    }

    return 0;
}

因此,前面的示例按预期运行并打印以下输出:

Foo Bar
--- ---
 0   0
 1   0
 2   0
 3   0
 4   0
 5   0
 6   0
 7   0
 8   0
 9   0

让我困惑的是变量在未初始化时的行为:

#include <stdio.h>

void test_var(void){
    static unsigned foo;    /* not initialized */
    unsigned bar;           /* not initialized */
    printf(" %u   %u\n", foo++, bar++);
}

int main(void){
    printf("Foo Bar\n");
    printf("--- ---\n");
    for(unsigned x = 0; x < 3; x++){
        test_var();
    }

    return 0;
}

输出:

Foo Bar
--- ---
 0   2
 1   3
 2   4
 3   5
 4   6
 5   7
 6   8
 7   9
 8   10
 9   11

所以 静态变量 的行为符合预期——获取默认值 0 并通过函数调用持续存在;但 自动变量 似乎也持续存在——尽管持有一个垃圾值,但它在每次调用中都会递增。

发生这种情况是因为 C 标准 中的行为未定义,还是标准中有一组规则可以解释这一点?

【问题讨论】:

  • 在我看来很像未定义的行为。在 test_var 函数周围添加更多变量和函数调用,“有趣”可能会随之而来。
  • 这是未定义的行为。这可能是因为变量bar 总是放置在相同的位置,并且在调用之间永远不会被覆盖。
  • 我几乎 100% 肯定这是一个重复的问题。
  • 所以它似乎持续存在的原因可能是因为我的代码过于简单以至于内存永远不会被覆盖?
  • @VilhelmGray 很有可能。如果您在循环体中也调用带有几个参数的另一个函数,则很有可能会覆盖放置 bar 的位置。

标签: c static scope initialization c99


【解决方案1】:

C 标准说对象的生命周期是保证存储的时间(参见例如 ISO/IEC 9899:TC3 的 6.2.4)。静态变量和全局变量的生命周期贯穿整个程序,为此,上述行为由标准保证。这些值在程序启动之前被初始化。对于自动,对象也处于恒定地址,但仅在其生命周期内得到保证。因此,尽管 bar 似乎在多个函数调用中保持活动状态,但您不能保证它。 这也是为什么你应该总是初始化你的变量,在你使用它之前你永远无法知道哪个变量在同一个位置。

我稍微修改了程序以打印静态和局部变量的地址:

#include <stdio.h>

void test_var(void){
    static unsigned foo;    /* not initialized */
    unsigned bar;           /* not initialized */
    printf(" %u   %u\t%p\t %p\n", foo++, bar++, &foo, &bar);

}

int main() {
    printf("Foo Bar\n");
    printf("--- ---\n");
    for(unsigned x = 0; x < 3; x++){
        test_var();
    }

    return 0;
}

这在我的计算机上产生了以下输出:

Foo Bar
--- ---
 0   33616  0x1067c  0xbee894fc
 1   33617  0x1067c  0xbee894fc
 2   33618  0x1067c  0xbee894fc

这表明在我的机器上,静态foo 和自动bar 在每次调用时都位于相同的地址,但这是巧合,C 标准并不能保证bar 始终是在同一个地址。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 2017-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多