为什么我们必须在使用之前初始化变量?

可能重复:
在C中声明的未初始化变量会发生什么? 它有价值吗?

现在我正在读Teach Yourself C in 21 Days 在第3章中,有一个这样的说明:

请勿使用尚未初始化的变量。 结果可能无法预测。

请向我解释为什么会这样。 该书没有提供进一步的说明。

声明变量时,它将指向一块内存。

访问变量的值将为您提供该段内存的内容。

但是,在变量初始化之前,该内存可以包含任何内容。 这就是为什么使用它是不可预测的。

其他语言可以通过在分配变量时自动初始化变量来帮助您,但作为C程序员,您使用的是一种相当低级的语言,不会假设您想对程序执行什么操作。 作为程序员,您必须明确告诉程序执行所有操作。

这意味着初始化变量,但它也意味着更多。 例如,在C中,您需要非常小心,在完成它们之后取消分配您分配的任何资源。 程序结束后,其他语言将自动清理; 但是在C中,如果你忘记了,你最终会发生内存泄漏。

C会让你做很多其他语言难以或不可能完成的事情。 但这种权力也意味着你必须对那些你认为理所当然的其他语言的家务管理工作负责。

因为,除非变量具有静态存储空间,否则它的初始值是不确定的。 你不能依赖它,因为标准没有定义它。 即使是静态分配的变量也应该初始化。 只需初始化您的变量,避免将来可能出现的问题。 没有充分的理由不初始化变量,有充分的理由反而做。

另一方面,不要相信任何声称在21天内教你X编程语言的书。 他们撒谎,给自己一本体面的书。

您最终可能会使用在当前方法范围之外声明的变量。

考虑以下

 int count = 0; while(count < 500) { doFunction(); count ++; } ... void doFunction() { count = sizeof(someString); print(count); } 

在C中,使用满足成为register变量要求的未初始化自动变量(非静态本地和参数变量)的值是未定义的行为,因为这些变量值可能已从寄存器中获取,某些平台可能会中止您的程序如果您阅读了这些未初始化的值。 这包括unsigned char类型的变量(这被添加到以后的C规范中,以适应这些平台)。

使用不满足作为register变量要求的未初始化自动变量的值,例如具有其地址的变量,只要您使用的C实现没有您使用的变量类型的陷阱表示,就可以了。 例如,如果变量类型是unsigned char ,则Standard要求所有平台不要在这些变量中存储陷阱表示,并且从中读取不确定值将始终成功并且不是未定义的行为。 类似intshort类型没有这样的保证,因此您的程序可能会崩溃,具体取决于您使用的C实现。

如果您没有明确地执行静态存储持续时间的变量,则始终初始化,因此您不必担心这里。

对于已分配存储持续时间( malloc …)的变量,同样适用于不满足作为register变量要求的自动变量,因为在这些情况下受影响的C实现需要从内存中读取程序,并且不会遇到寄存器读取可能引发exception的问题。

在C中,未初始化变量的值是不确定的。 这意味着您不知道它的值,它可能因平台和编译器而异。 对于诸如structunion类型的化合物也是如此。

为什么? 有时您不需要初始化变量,因为您要将其传递给填充变量的函数,而不关心变量中的内容。 您不希望强加给您的初始化开销。

怎么样? 可以从文字或函数返回值初始化原始类型。

 int i = 0; int j = foo(); 

使用聚合初始化语法可以将结构初始化为零:

 struct Foo { int i; int j; } struct Foo f = {0}; 

声明是迂腐的风险

请勿使用尚未初始化的变量。

是不正确的。 如果能更好地表达:

不要使用未初始化变量的值

该语言区分初始化赋值 ,因此第一个警告是,在这种意义上过于谨慎 – 您不需要为每个变量提供初始化器,但您应该在执行任何变量之前为变量分配初始化一个有用且有意义的值。随后使用其价值的运营。

所以以下是好的:

 int i ; // uninitialised variable i = some_function() ; // variable is "used" in left of assignment expression. some_other_function( i ) ; // value of variable is used 

即使调用some_function(), i也没有初始化。 如果要分配变量,则肯定是“使用”它(在这种情况下存储返回值); 它没有初始化的事实是无关紧要的,因为你没有使用它的价值。

现在,如果你坚持

不要使用未初始化变量的值

正如我所建议的那样,这个要求的原因变得很明显 – 为什么你会在不知道它包含有意义的东西的情况下获取变量的值? 一个有效的问题可能就是“为什么C不会使用已知值初始化auto变量。并且可能的答案是:

  • 任何编译器提供的任何值都不需要在应用程序的上下文中有意义 – 或者更糟糕的是,它可能具有与应用程序的实际状态相反的含义。

  • C被故意设计为没有隐藏的开销,因为它的根源是系统编程语言 – 初始化仅在显式编码时执行,因为它需要额外的机器指令和CPU周期来执行。

请注意, static变量始终初始化为零。 .NET语言(如C#)具有空值的概念,或者包含任何内容的变量,可以显式测试甚至分配。 C中的变量不能包含任何内容 ,但它包含的内容可能是不确定的,因此使用其值的代码将表现为非确定性。