c++ - C++中字符数组的意外输出

标签 c++ char

我对 C++ 非常缺乏经验,我编写了以下代码来了解字符和字符串的工作原理。

#include "stdio.h"
#include <iostream>
#include <string>

using namespace std;

int main()
{
    char asdf[] = "hello";
    char test[5] = {'h','e','l','l','o'};
    cout << test;
}

我本以为它会输出“hello”,但我却得到了“hellohello”,这让我很困惑。我做了一些实验:

如果我将 asdf 更改为另一个不同长度的字符串,它会正常输出“hello”。 如果我更改测试中的字符数量,它会正常输出“hello”。

我以为只有当两者长度相同时才会发生这种情况,但当我将它们都改为“hell”时,它似乎正常输出“hell”。

让事情变得更加困惑的是,当我让一位 friend 在他们的计算机上运行这段代码时,它输出了“hello”,然后是一个随机字符。

我正在 Ubuntu 上运行全新安装的代码块。有人知道这里发生了什么吗?

最佳答案

这是未定义的行为

原始 char*char[] C 和 C++ 中的字符串必须是 NULL-terminated .也就是说,字符串需要以 '\0' 结尾。特点。你的test[5]不这样做,所以打印输出的函数在最后一个 o 之后继续,因为它仍在寻找 NULL 终止。

由于字符串在 stack 上的存储方式(堆栈通常向较低地址增长),它遇到的下一个字节是asdf[]的字节。 ,您分配了 "hello" .这就是内存布局的实际样子,箭头表示内存地址(想想指针)增加的方向:

      ---->
  +-------------------
  |hellohello\0 ...
  +-------------------
        \_ asdf
   \_ test

现在在 C++ 和 C 中,字符串文字如 "hello"隐式以 NULL 终止,因此编译器写入一个隐藏的 '\0'在字符串的末尾后面。输出函数继续逐字符打印 asdf 的内容,直到到达隐藏的 '\0'。然后它停止了。

如果您要删除 asdf ,您可能会在第一个 hello 之后看到一些垃圾然后是段错误。但这是未定义的行为,因为您正在读取 test 的范围。大批。这也解释了为什么它在不同系统上的行为不同:例如,一些编译器可能决定以不同的顺序在堆栈上布置变量,因此在您 friend 的系统上,test实际上在栈上较低(记住,在栈上较低意味着在较高地址):

      ---->
  +-------------------
  |hello\0hello ...
  +-------------------
          \_ test
   \_ asdf

现在当你打印 test 的内容时, 它将打印 hello逐个字符,然后继续读取内存直到 \0被发现。 ...的内容高度特定于所用的体系结构和运行时,甚至可能是月相和一天中的时间(不完全是认真的),因此在您 friend 的机器上它会打印一个“随机”字符然后停止。

您可以通过添加 '\0' 来解决此问题或 0给你的test数组(您需要将大小更改为 6)。但是,使用 const char test[] = "hello";是解决这个问题的最明智的方法。

关于c++ - C++中字符数组的意外输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40057292/

相关文章:

java - 仅打印给定字符串中的 3 个连续字符

c++ - 在函数的输入参数中用 std::string 替换 char 数组

c++ - cin.get() 没有跳出循环

c++ - 如何有效地从给定另一个 vector 的 vector 中删除元素

c++ - 纹理管 OpenGL

c++ - 解决代码中模块之间的相互依赖

c - 在char中分配一个以上的字符

c++ - 使用 Opencv : BlobDetector 时出现 undefined reference 错误

c - 在 16 位微处理器上,我应该使用 short 数据类型而不是 int 吗?

java - 无法转换为 char 吗? : operator