空字符行为c ++

时间:2015-08-06 02:16:47

标签: c++ arrays string

#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*,则行为与我期望的一致。

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

6 个答案:

答案 0 :(得分:2)

字符串文字和std::string存储空终止字符串。

但是5 char的数组声明如下:

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

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

但编译器确实知道s的大小。它是s类型的一部分。它没有.size()std::stringstd::vector这样的便捷std::array功能,但你可以这样做:

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

或者更安全地使用C ++ 11:

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

或者在C ++ 17中:

std::size(s)

demo

阵列有一种腐烂指针的习惯,然后无法获得大小,你必须自己跟踪它。这就是C ++中首选std::stringstd::vectorstd::array的原因。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

  

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

大小取决于您提供的字符数。

  

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

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您的代码为char s[] = {'a','b','c','d','e'};,因此不会将\0放在char array的末尾。它将使用以下三种方法放置\0

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

因此,如果您使用上述三个中的任何一个,您将获得NULL个字符。

答案 5 :(得分:0)

“编译器如何知道数组何时结束?”:编译器从其声明中知道该数组有多少元素,并且这些信息可通过sizeof运算符获得。

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

出于这个原因,你不能使用cout&lt;&lt;如果您的字符串不是以空值终止的语句。