【问题标题】:local variable initialized to zero in C在C中初始化为零的局部变量
【发布时间】:2014-01-16 02:06:45
【问题描述】:

我以为C中的局部变量没有初始化。但是当我用 gcc 编译这段代码时。

void f() {
    static int s;
    int n;

    printf("static s = %d\n", s++);
    printf("local  n = %d\n", n++);

    f();
}

main() {
    f();
}

并运行这段代码,部分结果是:

static s = 0
local  n = 0
static s = 1
local  n = 0
static s = 2
local  n = 0
static s = 3
local  n = 0
static s = 4
local  n = 0
static s = 5
local  n = 0
...
static s = 261974
local  n = 0
static s = 261975
local  n = 0
static s = 261976
local  n = 0
static s = 261977
local  n = 0
static s = 261978
local  n = 0
static s = 261979
local  n = 0
static s = 261980
local  n = 0
static s = 261981
local  n = 0
Segmentation fault: 11

谁能解释一下?还是参考 C 不会初始化本地变量的标准参考?

【问题讨论】:

  • 行为未定义;任何事情都可能发生。
  • @wannik - 运气。但不要指望它。这是未定义的行为。最好打开编译器警告
  • 是的,未定义。另请参阅右侧“相关”下的几个先前答案。说真的,如果你希望它初始化为 0,请使用显式的初始值。
  • 尝试单次调用两次,无需递归。一些操作系统,如 Windows 空闲进程中的零空闲内存。因此堆栈块可能已分配为零。
  • @EdHeal 我没有收到使用 -Wall -Wextra 的警告,编译器警告标志是什么?

标签: c


【解决方案1】:

ISO/IEC 9899:TC3 WG14/N1256(C99 标准)第 6.7.8 节第 10 节:

如果具有自动存储持续时间的对象未初始化 明确地说,它的值是不确定的。

如果具有静态存储持续时间的对象未初始化 明确地,那么:

  • 如果有指针类型,则初始化为空指针;
  • 如果它具有算术类型,则将其初始化为(正或无符号)零;
  • 如果是聚合,则每个成员都根据这些规则进行初始化(递归);
  • 如果是联合,则根据这些规则(递归)初始化第一个命名成员。

您的变量符合第一类。不确定意味着它可以是任何东西(包括 0)。仅仅因为它在您执行的测试中为零,并不意味着它将永远为零,或者您可以依赖这种行为。根据编译选项和优化级别,即使使用相同的编译器,行为也可能会发生变化。

【讨论】:

【解决方案2】:

本地非static 变量未初始化——这通常意味着它们包含垃圾。

0 与其他任何垃圾值一样有效。但初始值也可以很容易地是42-12345

只是不要那样做。您需要确保不读取任何变量的值,除非它已被初始化。读取未初始化的变量具有未定义的行为,这意味着可能的行为不限于打印一些任意值。

这样做的一个好方法是使用显式初始化器:

int n = 0;

(顺便说一句,您缺少必需的#include <stdio.h>,而main 的正确声明是int main(void)。)

【讨论】:

  • 可能有值0x2A
  • 所以变量确实有一个值,只是没有任何特定的值——明白了。
  • @ScottHunter:至少在 2011 C 标准中,读取未初始化对象的行为是未定义的,所以不,它不一定有值。
  • 投反对票?如果我的回答有问题,我想知道。
【解决方案3】:

根据我的经验,它可能会或可能不会初始化为 0,具体取决于编译器和编译期间使用的标志。

【讨论】:

    【解决方案4】:

    您正在编写的内容表现出未定义的行为(我假设您会受到编译器的责骂)。这个编译器今天产生了一个具有这个输出的程序这一事实并不特别意味着什么。编译器可能只是将所有堆栈内存设置为零。或者堆栈可能正在通过先前归零的内存前进。或者堆栈完全停留在它所在的位置(毕竟编译器无法“展开”您的 main)并且 n 的位置恰好是一个零字。今天。

    【讨论】:

      【解决方案5】:

      如果变量在函数内部初始化,它不会自动初始化。当它在任何函数之外声明时,它会被初始化为 0。

      【讨论】:

      • 初始化不会在main中发生,而是在输入main之前发生。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 1970-01-01
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多