【问题标题】:Use of null character in strings (C++)在字符串中使用空字符 (C++)
【发布时间】:2012-07-20 15:27:27
【问题描述】:

我正在复习我的 C++,偶然发现了一个关于字符串、字符数组和空字符 ('\0') 的奇怪行为。以下代码:

#include <iostream>
using namespace std;

int main() {
    cout << "hello\0there"[6] << endl;

    char word [] = "hello\0there";
    cout << word[6] << endl;

    string word2 = "hello\0there";
    cout << word2[6] << endl;

    return 0;
}

产生输出:

> t
> t
>

幕后发生了什么?为什么字符串字面量和声明的 char 数组在索引 6 处存储了't'(在内部 '\0' 之后),而声明的字符串却没有?

【问题讨论】:

  • 当您cout &lt;&lt; word2 时会发生什么?这可能会让您深入了解正在发生的事情。
  • @philipvr 打印所有 3 个表示只生成字符串“hello”。
  • 如果他是cout &lt;&lt; word2,它会打印出hello,这并不能真正说明他的问题。

标签: c++ string arrays null-character


【解决方案1】:

据我记得,前两个本质上只是一个数组,而字符串的打印方式是继续打印,直到遇到\0。因此,在前两个示例中,您从字符串中第 6 个字符的点偏移开始,但在您的情况下,您将打印出第 6 个字符,即t

string 类发生的情况是,它将字符串复制到它自己的内部缓冲区中,并通过将字符串从数组的开头复制到它找到的第一个 \0 来实现。因此,t 不会被存储,因为它位于第一个 \0 之后。

【讨论】:

  • 另外,在string 的情况下,您的索引超出了string 的内存边界。你很幸运你的代码没有崩溃。
  • 附带说明,如果他真的想要复制整个字符串,他可以使用std::string word3("hello\0there", 11);
【解决方案2】:

因为采用const char*std::string 构造函数将其参数视为C 样式字符串。它只是从中复制,直到遇到空终止符,然后停止复制。

所以你的最后一个例子实际上是在调用未定义的行为; word2[6] 超出字符串的末尾。

【讨论】:

    【解决方案3】:

    您正在从char*(或衰减到那个的东西)构造一个字符串。这意味着适用 C 字符串的约定。那就是他们被'\0' 终止。这就是为什么word2 只包含"hello"

    【讨论】:

      【解决方案4】:

      问题是您根本没有打印字符串 - 您正在打印单个字符。

      char word [] = "hello\0there";//Array of char...
      cout << word[6] << endl;      //So word[6] is the char't' (NOT a string)
      
      string word2 = "hello\0there"; //std::string...
      cout << word2[6] << endl;      //so word2[6] is the char 't' (NOT a string as well)
      

      所以,您调用的是“char”重载,而不是“char*”或“string”重载,而 NULL 字符与它完全无关:您只是打印 word 的第 6 个字符, 和 word2 的第 6 个字符。

      如果我没看错你的意图,你的测试应该是:

      cout << &(word[6]) (char*, should print "there")
      cout << &(word2[6]) (char* as well, undefined behaviour pre-C++11)
      

      在 C++11 及更高版本中,这也将打印“那里”And be well defined

      【讨论】:

        猜你喜欢
        • 2020-10-30
        • 1970-01-01
        • 2017-09-26
        • 2014-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-16
        相关资源
        最近更新 更多