空字符行为c++

Null character behavior c++

本文关键字:c++ 字符      更新时间:2023-10-16
#include <iostream>
#include <string>
using namespace std;
int main() {
  string s = "hello";
  cout << s[5] << endl;
  return 0;
}

在上面的代码中,如果我打印s[5],它会正确打印一个NULL字符。但是如果我把代码改成这样:

#include <iostream>
#include <string>
using namespace std;
int main() {
  char[] s = {'a','b','c','d','e'};
  cout << s[5] << endl;
  return 0;
}

它不打印一个NULL字符,但随机的东西。如果我将字符串存储为stringchar*,则行为与我所期望的一致。

但是如果我显式地声明字符数组,编译器如何知道数组何时结束?数组的大小是否在编译时存储?

字符串字面值和 std::strings存储以空结尾的字符串。

但是一个包含5个char的数组声明如下:

char s[] = {'a','b','c','d','e'};

只包含5个char,没有空终止符。

但是编译器知道s的大小。它是s类型的一部分。它没有像std::string, std::vectorstd::array那样方便的.size()功能,但您可以通过以下操作获得:

sizeof(s) / sizeof(s[0])

或者在c++ 11中更安全:

std::extent<decltype(s)>::value 

或者c++ 17中的

std::size(s)
(演示)

数组有退化为指针的习惯,然后没有办法得到它的大小,你必须自己跟踪它。这就是为什么在c++中首选std::stringstd::vectorstd::array

字符串以空结束,const char*的处理方式与字符串相同。当你声明一个有大小的数组时,它被放在堆栈上,编译器不知道它的大小。数组越界异常不能在编译时确定。

c++中的string类有一个构造函数,如果没有显式添加,它自己会将null字符添加到传递给它的字符串中。但是,当使用char时,它只存储传递给它的内容(即),如果你想要一个空字符,你必须显式地在该字符的声明或定义中添加。

当您执行char[] s = {'a','b','c','d','e'};时,它将存储提到的字符,而不是其他字符。

如果我显式声明字符数组,编译器如何知道数组何时结束?

的大小由您提供的字符数决定。

数组的大小在编译时存储吗?

不,数组的大小是由分配给它的内存块决定的。(它不是单独存储在内存中,如果这是你的意思)

当你使用这个string s = "hello";时,字符串总是以空结束。

您的代码是char s[] = {'a','b','c','d','e'};,因此它不会将放在char array的末尾。它将把与三个方法放在下面:

1. char s[] = {'a','b','c','d','e', ''};
2. char s[] = "abcde";
3. string s = "abcde";

所以如果你使用上述三个字符中的任何一个,你将得到一个NULL字符。

"编译器如何知道数组何时结束?":编译器从数组的声明中知道数组有多少个元素,这些信息可以通过sizeof操作符获得。

无论如何,C风格的数组实际上没有大小,因为它们作为参数传递时隐式地转换为指针,并且它们的长度被删除(在我看来,这是C语言设计中的一个主要缺陷)。避免溢出是你的责任。

因此,不能使用count <<