3

我在 C++ 中做了一个基本的“猜我的数字游戏”,并且我添加了一个变量来表示人们猜数字的次数。然而,当游戏结束时,会显示一个随机的猜测值。像 1980046322 之类的东西。考虑到我没有在我的代码中添加任何非同寻常的东西,我无法弄清楚它为什么会这样做。

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
int randomNumber;
int guess;
int guesses;

srand((unsigned)time(0));
randomNumber = (rand()%10)+1;

cout << "I am thinking of a number between 1 to 10. Can you guess it?" << endl;

while(guess != randomNumber){
    cout << "That is not correct, try again.";
    guesses++;
    cin >> guess;
}

if(guess == randomNumber){
    cout << "Good Job. Guesses: " << guesses << endl;
    guesses++;
}

return 0;
}
4

6 回答 6

9

根据 C++11 标准的第 8.5/11 段:

如果没有为对象指定初始化器,则该对象是默认初始化的;如果不执行初始化,则具有自动或动态存储持续时间的对象具有不确定值。[ 注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。——尾注]

第 8.5/6 段解释了默认初始化对不同变量类型的意义:

默认初始化T类型的对象意味着:

— 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的);

— 如果 T 是数组类型,则每个元素都是默认初始化的;

否则,不执行初始化

由于T在您的情况下既不是类类型也不是数组类型(所有默认初始化的变量都具有 type int),因此不执行初始化并且初始值是不确定的。

此外,您的程序具有Undefined Behavior,因为它试图读取未初始化变量的值。这样做需要进行左值到右值的转换(尽管标准没有明确指定这一点,但可能是有意的,请参阅此 Q&A on SO),以及 C++11 标准的第 4/1 段规定:

非函数、非数组类型 T 的泛左值 (3.10) 可以转换为纯右值。53 如果 T 是不完整类型,则需要这种转换的程序是非良构的。如果泛左值所引用的对象不是 T 类型的对象,也不是从 T 派生的类型的对象,或者如果该对象未初始化,则需要此转换的程序具有未定义的行为。如果 T 是非类类型,则纯右值的类型是 T 的 cv 非限定版本。否则,纯右值的类型是 T.54

于 2013-02-22T18:03:42.583 回答
4

您尚未初始化一些变量,然后在为它们分配任何值之前使用它们。它们以未指定的值开始,看起来是随机的。你可以像这样修复它

int guess = 0;
int guesses = 0;
于 2013-02-22T18:02:05.450 回答
3

代码没有初始化guessor guesses,所以它们的初始值是不可预测的。

于 2013-02-22T18:02:00.973 回答
2

您不会将猜测初始化为 0。因此它将包含它开始使用的内存地址中的任何内容

于 2013-02-22T18:03:17.140 回答
2

您不初始化猜测,因此您不知道该值是什么。C/C++ 不对未初始化变量的值做任何保证。

始终初始化所有值是一个好习惯

int guesses = 0;

于 2013-02-22T18:03:34.967 回答
1

您没有将guesses变量初始化为零。

例如,如果您使用 g++ 编译代码,使用以下标志,问题就会变得很明显:

$ g++ -O2 -Wall foo.cpp 
foo.cpp: In function ‘int main()’:
foo.cpp:25:38: warning: ‘guesses’ may be used uninitialized in this function [-Wmaybe-uninitialized]

请注意,除了警告标志之外,还需要优化标志来触发警告,至少在 g++ 4.7.2 中是这样。

故事的寓意:启用编译器警告。

于 2013-02-22T18:03:46.267 回答