C++ 中未初始化的变量行为
Uninitialized variable behaviour in C++
我自己查了一下,我写了一个这样的程序
int main() {
int i;
cout << i;
return 0;
}
我运行程序几次,结果一直都是一样的,都是零。
我在C中试过,结果是一样的。
但是我的教科书说
If you don’t initialize an variable that’s defined
inside a function, the variable value remain undefined.That means the element takes on
whatever value previously resided at that location in memory.
当程序总是为变量分配空闲内存位置时,这怎么可能?它怎么可能不是零(我假设默认可用内存值为零)?
If you don’t initialize an variable that’s defined inside a function, the variable value remain undefined.
这一位是真的。
That means the element takes on whatever value previously resided at that location in memory.
这个位不是。
有时在实践中会发生这种情况,您应该意识到 归零 或 不归零 完全符合这个理论,对于任何给定 运行 你的程序。
理论上,您的编译器实际上可以根据需要为该整数分配一个随机初始值,因此尝试对此合理化是完全没有意义的。但是让我们继续假设 "the element takes on whatever value previously resided at that location in memory"…
How could it be something rather than zero(I assume that default free memory value is zero)?
好吧,这就是您假设时发生的情况。 :)
How's this possible when the program always assign a free memory
location to a variable? How could it be something rather than zero?
让我们来看一个实际实现的例子。
假设它利用堆栈来保存局部变量。
void
foo(void)
{
int foo_var = 42;
}
void
bar(void)
{
int bar_var;
printf("%d\n", bar_var);
}
int
main(void)
{
bar();
foo();
bar();
}
上面完全损坏的代码说明了这一点。在我们调用 foo 之后,foo_var 被放置在堆栈上的某个位置被设置为 42。当我们调用 bar 时,bar_var 占据了那个确切的位置。事实上,执行代码会导致打印 0 和 42,表明 bar_var 值不能依赖,除非初始化。
现在应该很清楚需要局部变量初始化了。但是 main 会是个例外吗?有没有什么东西可以与堆栈一起玩,结果给我们一个非零值?
是的。 main 不是您程序中执行的第一个函数。事实上,设置所有内容需要 吨 的工作。任何这项工作都可能使用堆栈并在其上留下一些非零值。您不仅不能期望在不同的操作系统上有相同的值,而且它很可能会在您现在使用的系统上突然发生变化。有兴趣的可以google换"dynamic linker".
最后,C语言标准连栈这个词都没有。为局部变量设置 "place" 留给编译器。它甚至可以从给定寄存器中发生的任何事情中随机获取垃圾。它真的可以是 任何东西。事实上,如果未定义的行为被触发,编译器可以自由地做任何它想做的事。
静态变量和全局变量初始化为零:
Global:
int a; //a is initialized as 0
void myfunc(){
static int x; // x is also initialized as 0
printf("%d", x);}
Where as non-static variables or auto variables 即局部变量是 indeterminate (indeterminate 通常意味着它可以做任何事情。它可以是零,它可以是那里的值,它可以使程序崩溃)。在赋值之前读取它们会导致未定义的行为。
void myfunc2(){
int x; // value of x is assigned by compiler it can even be 0
printf("%d", x);}
它主要取决于编译器,但在大多数情况下,编译器会预先假定该值为 0
此代码调用未定义的行为 (UB),因为使用的变量未初始化。
当使用警告标志时,编译器应该发出警告,例如 -Wall
:
warning: 'i' is used uninitialized in this function [-Wuninitialized]
cout << i;
^
碰巧,在您的系统上 运行,它的值为 0。这意味着变量分配给的垃圾值恰好为 0,因为内存剩余有这么建议的
但是,请注意,kernel zeroes appear relatively often。这意味着我的系统输出结果为零是很常见的,但这并不能保证,也不应被视为承诺。
我自己查了一下,我写了一个这样的程序
int main() {
int i;
cout << i;
return 0;
}
我运行程序几次,结果一直都是一样的,都是零。 我在C中试过,结果是一样的。
但是我的教科书说
If you don’t initialize an variable that’s defined inside a function, the variable value remain undefined.That means the element takes on whatever value previously resided at that location in memory.
当程序总是为变量分配空闲内存位置时,这怎么可能?它怎么可能不是零(我假设默认可用内存值为零)?
If you don’t initialize an variable that’s defined inside a function, the variable value remain undefined.
这一位是真的。
That means the element takes on whatever value previously resided at that location in memory.
这个位不是。
有时在实践中会发生这种情况,您应该意识到 归零 或 不归零 完全符合这个理论,对于任何给定 运行 你的程序。
理论上,您的编译器实际上可以根据需要为该整数分配一个随机初始值,因此尝试对此合理化是完全没有意义的。但是让我们继续假设 "the element takes on whatever value previously resided at that location in memory"…
How could it be something rather than zero(I assume that default free memory value is zero)?
好吧,这就是您假设时发生的情况。 :)
How's this possible when the program always assign a free memory location to a variable? How could it be something rather than zero?
让我们来看一个实际实现的例子。
假设它利用堆栈来保存局部变量。
void
foo(void)
{
int foo_var = 42;
}
void
bar(void)
{
int bar_var;
printf("%d\n", bar_var);
}
int
main(void)
{
bar();
foo();
bar();
}
上面完全损坏的代码说明了这一点。在我们调用 foo 之后,foo_var 被放置在堆栈上的某个位置被设置为 42。当我们调用 bar 时,bar_var 占据了那个确切的位置。事实上,执行代码会导致打印 0 和 42,表明 bar_var 值不能依赖,除非初始化。
现在应该很清楚需要局部变量初始化了。但是 main 会是个例外吗?有没有什么东西可以与堆栈一起玩,结果给我们一个非零值?
是的。 main 不是您程序中执行的第一个函数。事实上,设置所有内容需要 吨 的工作。任何这项工作都可能使用堆栈并在其上留下一些非零值。您不仅不能期望在不同的操作系统上有相同的值,而且它很可能会在您现在使用的系统上突然发生变化。有兴趣的可以google换"dynamic linker".
最后,C语言标准连栈这个词都没有。为局部变量设置 "place" 留给编译器。它甚至可以从给定寄存器中发生的任何事情中随机获取垃圾。它真的可以是 任何东西。事实上,如果未定义的行为被触发,编译器可以自由地做任何它想做的事。
静态变量和全局变量初始化为零:
Global:
int a; //a is initialized as 0
void myfunc(){
static int x; // x is also initialized as 0
printf("%d", x);}
Where as non-static variables or auto variables 即局部变量是 indeterminate (indeterminate 通常意味着它可以做任何事情。它可以是零,它可以是那里的值,它可以使程序崩溃)。在赋值之前读取它们会导致未定义的行为。
void myfunc2(){
int x; // value of x is assigned by compiler it can even be 0
printf("%d", x);}
它主要取决于编译器,但在大多数情况下,编译器会预先假定该值为 0
此代码调用未定义的行为 (UB),因为使用的变量未初始化。
当使用警告标志时,编译器应该发出警告,例如 -Wall
:
warning: 'i' is used uninitialized in this function [-Wuninitialized]
cout << i;
^
碰巧,在您的系统上 运行,它的值为 0。这意味着变量分配给的垃圾值恰好为 0,因为内存剩余有这么建议的
但是,请注意,kernel zeroes appear relatively often。这意味着我的系统输出结果为零是很常见的,但这并不能保证,也不应被视为承诺。