我正在刷新我的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'
,但声明的字符串不存在?
答案 0 :(得分:10)
根据我的记忆,前两个本质上只是一个数组,打印字符串的方式是继续打印,直到遇到\0
。因此,在前两个示例中,您从字符串中第6个字符的点偏移量开始,但在您的情况下,您将打印出第{6个字符t
。
string
类会发生什么,它会将字符串的副本复制到它自己的内部缓冲区中,并通过将字符串从数组的开头复制到第一个\0
来实现。认定。因此,t
未存储,因为它位于第一个\0
之后。
答案 1 :(得分:5)
因为std::string
构造函数将const char*
视为C样式字符串。它只是从它复制,直到它达到空终止符,然后停止复制。
所以你的最后一个例子实际上是在调用未定义的行为; word2[6]
越过字符串的结尾。
答案 2 :(得分:4)
您正在构建一个来自char*
的字符串(或者腐烂的东西)。这意味着适用于C字符串的约定。那就是他们被'\0'
终止了。这就是word2
仅包含"hello"
。
答案 3 :(得分:0)
问题在于您根本不打印字符串 - 您正在打印单个字符。
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”And be well defined