【问题标题】:Assigning pointer to uninitialized variable changes it value?将指针分配给未初始化的变量会改变它的值吗?
【发布时间】:2011-09-19 08:23:50
【问题描述】:

我在 VisualStudio2010 中玩 c++

请解释为什么会发生这种情况:

int a, b;
int *p, *q;
cout << a << " " << b;

打印出“0 0”。很好理解,未初始化的整数应该是0; 但是

int a, b;
int *p, *q;
p = &a;
cout << a << " " << b;

输出为“1792816880 0”

因此,如果我将指针分配给未初始化的变量,它会更改默认值。 为什么?

编辑澄清:问题不在于未初始化变量的值

int a; int *p;
cout << a; // would be 0, because it's loacal variable
p = &a;
cout << a; //not 0;

如何获取 a 的指针可以改变它的值? 当我们初始化变量时,我们分配空间,一些位,它们可以是任何东西,但是“p = &a”真的会改变这个空间中的位吗?

【问题讨论】:

  • 有趣。在 Fedora 15 x64_86 下的 G++ 4.6.0 下也会发生类似的情况。
  • 提高项目设置中的警告级别。这将检测未初始化变量的使用情况。
  • 没有。不对。 未初始化的整数应该是0

标签: c++ visual-studio-2010 pointers


【解决方案1】:

这很好理解,未初始化的整数应该是0

没有。

不能保证,它取决于存储类,如果你的 int 是局部变量,它有一个自动存储,它不必是 0。

访问统一变量会导致未定义行为,并且您的代码会导致未定义行为。一旦出现未定义的行为,所有的赌注都将被取消,并且无法解释该行为。

关于未定义的行为,

C++ 标准第 1.3.24 节规定:

允许的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现(无论是否发出诊断消息),到终止翻译或执行(发出诊断消息)。

编辑:
鉴于上述这是未定义的行为,一个人不应该编写任何依赖于这种行为的代码,事实上,一个人甚至不应该考虑编写这样的代码。我发现深入研究所有这些编译器的实现以寻求解释为什么它会以这种方式工作是无关紧要的,也是徒劳的。

如果有人觉得这个回复很顽固,你可以随意投反对票。如果反对票数超过赞成票数,我会知道答案不受欢迎,我会删除它。

【讨论】:

  • 我认为“未定义行为”的辩护不能回答问题。
  • @trojanfoe 这是唯一可能的答案。程序的行为是未定义的,所以几乎任何事情都可能发生。
  • 这是一种逃避。谁能说明为什么它在 Visual Studio 和 GNU 编译器下都这样做?
  • @Als:C++ 是一种语言,而不是一种实现。您的“这是未定义的行为,不要这样做”的方法适用于“X 似乎在 C++ 中工作,我应该这样做吗?”形式的问题,但不是在这里。这段代码可以解释一下,你只要务实一点。我认为一个合适的答案是“首先,不要这样做。读取未初始化的变量是 UB,你不应该依赖 UB。也就是说,这就是为什么两个看似无关的事情是相关的......”
  • 我认为问题在于,该行为无法按标准解释。正如 GMan 所说,可以参考实现细节来解释特定实现(或多个实现)的行为。对 Visual Studio 2010 足够熟悉(或者可能只是查看发出的代码)的人可以准确解释为什么会发生这种情况。有时你甚至可以预测垃圾值...
【解决方案2】:

这是 C++ 中的“未定义行为”。

当您不在 C++ 中初始化变量时,它并不总是为零。那只是偶然。内存被分配,之前在那个内存位置的垃圾值会一直输出到初始化为止。

【讨论】:

    【解决方案3】:

    未定义未初始化值的值。没有默认值。可以显示任何值。

    您所做的任何看似不相关的操作都可能会更改垃圾的底层值,软件将作为对未定义值查询的回答而提供给您。

    底线是,不要推测应该发生什么未定义的行为。它只是未定义的 - 不要编写具有未定义行为的代码。

    【讨论】:

      【解决方案4】:

      这是未定义的行为,但这里有一些关于可能发生的猜测:

      在第一个代码示例中,从未获取变量的地址,因此编译器可能选择将它们保存在寄存器中,并且它们从不存在于主存储器中,而寄存器的值恰好为 0。

      在第二个代码示例中,获取地址,因此变量必须在内存中(在堆栈上),这样它才能有地址。只是碰巧现有的数据有一些随机垃圾。

      【讨论】:

        【解决方案5】:

        你有一堆永远不会被写入的变量。编译器可能决定不为这些变量分配存储空间。这可能看起来很苛刻,但它是合理的:现代编译器在细粒度级别上分配变量存储,并且某些变量可能在某些分支上未使用。为什么在不需要的时候还要分配内存呢?

        现在,如果您从一个“变量”中读取,而该“变量”因为您从未写入过而没有分配内存,会发生什么情况?你会得到一些随机数据,很可能是另一个变量。或者是段错误 - 未定义的行为有多种形式。

        现在举第二个例子:在这里你写入一个变量p。由于a 不需要任何内存分配(缺少写入),它很可能别名为pp 的值,重新解释为 int 很可能是 1792816880。

        【讨论】:

          【解决方案6】:

          C++ 不会在声明时初始化变量,它只是为它们分配 RAM 内存。无论您是否使用指针,它们都可以在初始化之前使用任何值。 您应该始终在使用前初始化变量。

          【讨论】:

          • 内存?这些是存储在堆栈中的变量!
          • @trojanfoe:你说堆栈不是 RAM 吗?
          • 当然不是,但它的分配方式与堆不同。
          • 但是 C++ 不会对任何原始类型的变量执行任何操作,直到您为其赋值。 IE。它不会用零填充它或做一些其他的魔法。
          • 除非您将其地址分配给另一个变量,否则似乎。
          【解决方案7】:

          未初始化的本地整数在 C++ 中不保证为 0。它们是“垃圾”,因此它们可以是任何值,包括 0。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-04
            • 2017-02-13
            • 1970-01-01
            • 1970-01-01
            • 2015-07-11
            • 2016-08-26
            相关资源
            最近更新 更多