【问题标题】:When I go over the array value, it prints a random number. Why is this? [duplicate]当我检查数组值时,它会打印一个随机数。为什么是这样? [复制]
【发布时间】:2016-12-25 04:52:25
【问题描述】:

截至昨天,我目前正在学习 C++,并且遇到了一个名为 array 的新事物。到目前为止,我对它们的了解是它们可以以某种表格形式保存数据,并且您可以修改/读取它们保存的数据。

由于我正在试验 C++,我想我会尝试打破它,这让我现在就问这个问题。当我尝试从未指定的值读取时,我得到一个数字,但我不确定为什么会导致它。

int lotteryNumbers[5] = {10, 20, 30, 40, 50};
// Yes, I know that the loop count is 5!
    for (int loopCount = 0; loopCount <= 5; loopCount++) {
        cout << lotteryNumbers[loopCount] << endl;
    }

我的输出是;

10
20
30
40
50
13439729 <-- What is this sourcery?!

如果能指导我学习这种复杂的语言,我们将不胜感激。

谢谢, 内森。

编辑:感谢您的帮助。现在标记为重复。 :D

【问题讨论】:

  • 你有 5 个数字,你正在读 6 个。 0、1、2、3、4、5。不是巫术,只是常识。如果您刚开始,请获得一本关于 C++ 的好书;通过提出关于 SO 的问题来学习并不是很有效。
  • @JonathanPotter 我知道我正在阅读第六个值。我想知道这个数字是什么原因,为什么是'13439729'?
  • 它恰好在那个被解释为 int 的内存位置中发生的事情
  • 为什么这个答案会获得反对票?这是一个很好的答案,除了它是重复的:)
  • 哎呀,没想到它是复制品。我是这个网站的新手,所以我不确定如何轻松找到东西。 :p

标签: c++


【解决方案1】:

C++ 让您能够自爆:数组在运行时没有边界检查

您需要确保只引用数组中的索引。

读取数组外索引的行为是未定义任何事情都可能发生:包括打印内存中该位置的内容(这很可能在您的情况下发生 - 请与您的调试器联系)。否则编译器会吃掉你的猫。

【讨论】:

  • @Nathan 虽然相邻内存可能是潜在的解释,但过多地关注这一点可能会导致您进入一个在 C 和 C++ 初学者程序员中普遍存在的不一致的伪低级思维世界。最好关注答案中指出行为是undefined 并且anything 可能发生的部分。从长远来看,它将为您提供更好的 C 和 C++ UB 心智模型。
  • 你忘了std::vectorstd::array的强制推荐:)
  • @TheodorosChatzigiannakis 我刚刚在 cplusplus.com 上查找了内存,我实际上只是关闭了我的浏览器,因为它看起来很复杂。如果我得到一个我不理解的值,我只会认为它是 undefined 正如你所说的那样。 :)
  • @Nathan:我发现你只需要在 5 小时后市场开市时,在生产服务器上的凌晨 3 点调试会话期间检查内存。最好提前学习如何使用这些工具。恕我直言,调试技能比编程技能更重要。
  • @Nathan Undefined 是规范所说的未定义。有时一个奇怪的值是非常明确的(即它是可移植的,并且会被未来的编译器和所有优化通过)但仍然表明您的业务逻辑中存在错误。
【解决方案2】:

数组在运行时没有边界检查。您总共有 5 个条目,从 0 开始,最终为 4。lotteryNumbers[5] 将返回一个垃圾值,因为最后一个索引是 4。

应该是:

int lotteryNumbers[5] = {10, 20, 30, 40, 50};
// Yes, I know that the loop count is 5!
    for (int loopCount = 0; loopCount <= 4; loopCount++) {
        cout << lotteryNumbers[loopCount] << endl;
    }

最佳做法是使用数组的大小。

【讨论】:

    【解决方案3】:

    与 Java、C# 或 Python 等另一种“现代”语言不同,C++ 具有“不为不使用的东西付费”的理念。数组绑定检查需要一些运行时开销,而其他没有数组绑定错误的“合法”程序则不需要。

    当代码lotteryNumbers[5]被执行时,程序陷入Undefined Behavior。 C++ 标准没有指定如果发生未定义的行为会发生什么。在这种情况下,程序会读取一些未初始化的堆栈内存,因此您可以看到像 13439729 这样的“垃圾”值。

    如果要绑定检查,可以使用std::array&lt;&gt;::at函数。

    #include <array>
    
    std::array<int, 5> lotteryNumbers = { 10, 20, 30, 40, 50 };
    std::cout << lotteryNumbers.at(5); // throw std::out_of_range
    

    请注意,我使用std::array,而不是普通数组。它是一个现代风格的数组,是在 C++11 中添加的。

    【讨论】:

      猜你喜欢
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多