可能重复:
What happens to a declared, uninitialized variable in C? Does it have a value?
现在我正在阅读Teach Yourself C in 21 Days
。在第3章中,有一个这样的说明:
请勿使用尚未初始化的变量。结果可以 不可预测的。
请向我解释为什么会这样。这本书没有提供进一步的说明。
答案 0 :(得分:8)
因为,除非变量具有静态存储空间,否则它的初始值是不确定的。你不能依赖它,因为标准没有定义它。即使是静态分配的变量也应该初始化。只需初始化您的变量,避免将来可能出现的问题。没有充分的理由不对变量进行初始化,有充分的理由反过来。
另一方面,不要相信任何声称在21天内教你X编程语言的书。他们撒谎,给自己一本体面的书。
答案 1 :(得分:3)
声明变量时,它将指向一段内存。
访问变量的值将为您提供该段内存的内容。
然而,在变量初始化之前,该内存可能包含任何内容。这就是为什么使用它是不可预测的。
其他语言可以通过在分配变量时自动初始化变量来帮助您,但作为C程序员,您使用的是一种相当低级的语言,不会假设您想对程序执行什么操作。作为程序员,您必须明确告诉程序执行所有操作。
这意味着初始化变量,但它也意味着更多。例如,在C中,您需要非常小心,在完成它们之后取消分配您分配的任何资源。程序结束后,其他语言将自动清理;但是如果你忘记了C,你最终会发生内存泄漏。
C会让你做很多其他语言难以或不可能完成的事情。但这种权力也意味着你必须对你认为理所当然的其他语言的家务管理工作负责。
答案 2 :(得分:1)
在C中,未初始化变量的值是不确定的。这意味着您不知道它的值,它可能因平台和编译器而异。对于struct
和union
类型的化合物也是如此。
为什么?有时您不需要初始化变量,因为您要将其传递给填充变量的函数,而不关心变量中的内容。您不希望强加给您的初始化开销。
如何?可以从文字或函数返回值初始化原始类型。
int i = 0;
int j = foo();
结构可以使用聚合初始化语法初始化为零:
struct Foo { int i; int j; }
struct Foo f = {0};
答案 3 :(得分:1)
您最终可能会使用在当前方法范围之外声明的变量。
考虑以下
int count = 0;
while(count < 500)
{
doFunction();
count ++;
}
...
void doFunction() {
count = sizeof(someString);
print(count);
}
答案 4 :(得分:1)
在C中,使用满足register
变量要求的未初始化自动变量(非静态本地变量和参数变量)的值是未定义的行为,因为这些变量值可能已从寄存器中获取如果您阅读了这些未初始化的值,某些平台可能会中止您的程序。这包括unsigned char
类型的变量(这被添加到以后的C规范中,以适应这些平台)。
使用不满足成为register
变量要求的未初始化自动变量的值,例如具有其地址的变量,只要您使用的C实现没有陷阱表示就可以了您使用的变量类型。例如,如果变量类型为unsigned char
,则标准要求所有平台不要将陷阱表示存储在此类变量中,并且从中读取不确定值将始终成功并且不是未定义的行为。像int
或short
这样的类型没有这样的保证,因此您的程序可能会崩溃,具体取决于您使用的C实现。
如果您没有明确地执行静态存储持续时间的变量,则始终会初始化,因此您不必担心这里。
对于已分配存储持续时间(malloc
...)的变量,同样适用于不满足register
变量要求的自动变量,因为在这些情况下受影响C实现需要使您的程序从内存中读取,并且不会遇到寄存器读取可能引发异常的问题。
答案 5 :(得分:1)
冒着迂腐的风险,声明
请勿使用尚未初始化的变量。
不正确。如果表达得更好:
不要使用未初始化变量的值。
该语言区分初始化和赋值,因此第一个警告是,在这个意义上过于谨慎 - 您不需要为每个变量提供初始化,但您应该在执行随后使用其值的任何操作之前,已经为或初始化了一个带有有用且有意义的值的变量。
所以以下情况很好:
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#)具有空值的概念,或者包含 nothing 的变量,可以显式测试甚至分配。 C中的变量不能包含 nothing ,但它包含的内容可能是不确定的,因此使用其值的代码将具有非确定性。