10

我正在复习我的 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 数组存储't'at 索引 6(在 internal 之后'\0'),但声明的字符串不存储?

4

4 回答 4

9

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

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

于 2012-07-20T15:30:34.533 回答
6

因为std::string接受 a 的构造函数const char*将其参数视为 C 风格的字符串。它只是从中复制,直到遇到空终止符,然后停止复制。

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

于 2012-07-20T15:32:00.480 回答
4

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

于 2012-07-20T15:30:20.497 回答
1

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

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 字符与它完全无关:您只是打印单词的第 6 个字符,而word2 的第 6 个字符。

如果我正确阅读了您的意图,则您的测试应为:

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

在 C++11 及更高版本中,这也将打印 "there" 并被明确定义

于 2015-10-19T13:28:44.943 回答