0

受到这篇文章的回答的启发。为什么这是 NaN

我有以下代码:

int main()
{
   const int weeks = 10;
   const int salespersons = 9;
   const int days = 30;

   double weekly_sales[weeks][salespersons][days];
   double total_weekly_sales[weeks];
   double total_overall_weekly_sales[salespersons];
   int a;
   cout << "a = " << a <<endl;
   cout << total_weekly_sales[0] <<endl; 
   for(int w=0; w < weeks;w++)
   {
      for(int d =0; d < days; d++)
      {  
          for(int s=0; s < salespersons; s++)
          {
              total_weekly_sales[w]+=weekly_sales[w][s][d];
              total_overall_weekly_sales[s]+= weekly_sales[w][s][d];
          }
       }  
    }
 cout << total_weekly_sales[0] <<endl;
}

它将输出以下内容:

a = 0
0
0

在 gcc 4.5.3 下,带有编译选项-Wall.

我还在这里编译了代码:http: //liveworkspace.org/code/94SOj $2。与上面相同的输出。

我也在VS2010下编译了代码。VS2010 给出警告如下:

warning C4700: uninitialized local variable 'a' used
warning C4700: uninitialized local variable 'total_weekly_sales' used

当我跑的时候:

Run-Time Check Failure #3 - The variable 'a' is being used without being initialized.

我知道不初始化局部变量并使用它们是不好的做法。我也明白这会有问题。

我的问题是:

在 C++ 标准中:有没有地方说使用未初始化的局部变量会导致未定义的行为?为什么它在不同的编译器下表现不同?这是否意味着该标准实际上并未强制要求所有编译器都应针对using uninitialized local variable? 那么,您如何从编译器输出中判断它是未定义的行为呢?

谢谢。

4

2 回答 2

6

是的,该标准明确指出未初始化对象上的左值到右值转换将导致未定义的行为:

非函数、非数组类型的 glvalue (3.10)T可以转换为纯右值。如果T是不完整类型,则需要进行此转换的程序格式错误。如果泛左值引用的对象不是 T 类型的对象,也不是从 T 派生的类型的对象,或者如果该对象未初始化,则需要此转换的程序具有未定义的行为。

任何需要使用对象值的东西都会调用左值到右值的转换。

未定义的行为定义为:

本国际标准没有要求的行为

所以是的,一个具有未定义行为的程序可以做任何事情,即使它看起来工作正常。所以你不能总是从程序的输出中识别出未定义的行为。真正的解决方案是编写正确的、定义明确的代码。为此,我强烈建议您随身携带一份 C++ 标准的副本。编写代码并对它的作用做出假设是一件非常糟糕的事情,所以如果你写过任何你不确定的 C++,一定要检查一下。

为什么标准中存在未定义的行为?首先,这意味着你真的只能得到你想要的。如果将未初始化的变量定义为自动获取值 0(例如),则您声明未初始化的每个变量都将有一些额外的操作将值设置为 0,这可能是不需要的。该标准简单地说,使用未初始化变量的值是未定义的,允许它留下已经存在于该内存位置的垃圾值。无需额外费用。

其次,它允许编译器基于任何 C++ 程序员都会编写理智、定义明确的代码的假设进行优化。

于 2013-04-04T19:48:14.787 回答
1

未定义的行为就是这个意思。行为未定义。有些编译器会很好并警告你,有些编译器会做一些疯狂的事情。从理论上讲,他们可以在这种情况下擦除您的硬盘驱动器,但这将是一个非常糟糕的编译器。

具体来说,未初始化的变量可以具有任何值。实际上,如果您的程序刚刚启动,它通常为 0(操作系统提供的一项安全功能,用于阻止您的程序从旧程序读取内存),但是一旦运行了一段时间,它很有可能是一个完全随机的值,因为内存以前被另一个函数使用过。因此发出警告。如果您忽略它,您的程序将无缘无故地随机失败。

于 2013-04-04T19:50:15.327 回答