我对编程很陌生,对C++也很陌生,最近我遇到了字符串。
为什么我们需要在字符列表的末尾使用null终止符?
我读过这样的答案,因为我们可能不会使用数组的所有空格,因此我们需要程序的null终止符来知道字符串的结束位置,例如char[100] = "John"
但是为什么程序不能循环遍历数组来检查填充了多少空间,从而决定长度呢?
如果单词"John"
的数组中只填充了四个字符,那么其他空格填充了什么?
数组char john[100] = "John"
中的其他字符将用零填充,这些字符都是空终止符。通常,当您初始化一个数组,但没有提供足够的元素来填充它时,剩余的元素将默认初始化:
int foo[3] {5}; // this is {5, 0, 0}
int bar[3] {}; // this is {0, 0, 0}
char john[5] = "John"; // this is {'J', 'o', 'h', 'n', 0}
char peter[5] = "Peter"; // ERROR, initializer string too long
// (one null-terminator is mandatory)
另请参阅阵列初始化的cppreference。要找到这样一个字符串的长度,我们只需循环遍历这些字符,直到找到0
并退出。
C++中null终止字符串背后的动机是确保与使用null终止字符串的C库的兼容性。另请参阅What';空终止字符串的基本原理是什么?
像std::string
这样的容器不要求字符串以null结尾,甚至可以存储包含null字符的字符串。这是因为它们分别存储字符串的大小。然而,std::string
的字符通常以null结尾,因此std::string::c_str()
不需要修改底层数组。
只有C++的库很少(如果有的话(在函数之间传递C字符串。
空终止符的存在是一个设计决策。它的作用是标记绳子的末端。还有其他方法可以做到这一点,例如在Pascal中,字符串的第一个元素是它的大小,因此不需要null终止符。
在您给出的示例中,只有数组的前5个元素将被初始化,其余元素为零初始化。注意我是怎么说5个元素而不仅仅是4个元素的。第五个元素是null终止符。
当然,程序可以循环字符串来找出它的长度,但它如何知道何时停止循环?
nul终止符是告诉填充了哪些空格。包括nul终止符在内的所有内容都已填充。之后的一切都没有。
对于数组的哪些元素已被填充,并没有一个通用的概念。数组包含一定数量的元素;其大小是在创建时确定的。它的所有元素最初都有一定的价值;一般来说,无法通过查看元素的值来确定哪些元素被赋予了值,哪些元素没有被赋予值。
字符串是CCD_ 8和的数组;结束";字符串的由一个nul字符标记。大多数字符串操作函数都依赖于这种约定。
字符串文字,例如"John"
,是char
的数组。"John"
在阵列中有5个元素:'J'
、'o'
、'h'
、'n'
、' '
。例如,函数strcpy
复制字符,直到它看到nul终止符:
char result[100]; // no meaningful values here
strcpy(result, "John");
在调用strcpy
之后,result
的前五个元素是'J'
、'o'
、'h'
、'n'
和' '
。其余的数组元素没有任何有意义的值。
如果我没有提到这种风格的字符串来自C,通常被称为C风格的字符串,那我就太失职了。C++支持所有的C字符串,但它也有一个更复杂的字符串概念std::string
,这是完全不同的。一般来说,应该使用C++风格的字符串,而不是C风格的字符串。