为什么具有单独字符的字符数组不像字符串文字那样以 null 终止符结尾?

Why don't char arrays with separate chars end with a null-terminator unlike string literals?

本文关键字:字符 null 终止 结尾 文字 字符串 单独 数组 为什么      更新时间:2023-10-16

我在 c++ 中玩弄 char 数组并编写了这个程序:

int main()
{
char text[] = { 'h', 'e', 'l', 'l', 'o' };  //arrays initialised like this 
                                            //will have a size of the number 
                                            //of elements that you see
char text2[] = "hello"; //arrays initialised like this will have a size of 
                        //the number of elements that you see + 1 (0 on the 
                        //end to show where the end is
cout << endl;
cout << "The size of the first array is: " << sizeof(text) << endl;
cout << endl;
for (int i = 0; i < sizeof(text); i++)
{
    cout << i << ":" << text[i] << endl;
}
cout << endl;
cout << "The size of the first array is: " << sizeof(text2) << endl;
cout << endl;
for (int i = 0; i < sizeof(text2); i++)
{
    cout << i << ":" << text2[i] << endl;
}
cout << endl;
cin.get();
return 0;
}

这个程序给了我输出:

The size of the first array is: 5
0:h
1:e
2:l
3:l
4:o
The size of the first array is: 6
0:h
1:e
2:l
3:l
4:o
5:

我的问题是:与使用字符串文字初始化字符数组不同,使用单独的字符初始化字符数组末尾不会有空终止符 (0( 是否有特殊原因?

大括号初始值设定项仅提供数组的指定值(或者,如果数组较大,则其余项为默认值(。即使项目是char值,它也不是字符串。 char只是最小的整数类型。

字符串文本表示以零结尾的值序列。

就这样。

非正式地说,它是添加 NUL 终止符的 "foo" 形式的字符串文本中的第二个引号字符。

在C++中,"foo"是一种const char[4]类型,在某些情况下会衰减const char*

这就是语言的工作方式,仅此而已。它非常有用,因为它与所有标准库函数很好地吻合,这些函数将字符串建模为指向 NUL 终止的 char 数组中第一个元素的指针。

用类似char text[] = { 'h', 'e', 'l', 'l', 'o' };的东西拼接一个额外的元素会非常烦人,并且可能会给语言带来不一致。例如,你会为signed charunsigned char做同样的事情吗?那int8_t呢?

一个字符串文字,例如这个"hello"具有常量字符数组的类型,并按以下方式初始化

const char string_literal_hello[] = { 'h', 'e', 'l', 'l', 'o', '' };

可以看出,字符串文本的类型是 const char[6] 。它包含六个字符。

因此,该声明

char text2[] = "hello"; 

也可以这样写

char text2[] = { "hello" }; 

事实上,被替换为以下声明

char text2[] = { 'h', 'e', 'l', 'l', 'o', '' };

也就是说,字符串文本用作字符数组的初始值设定项,其所有字符都用于初始化数组。

您可以通过多种方式自行终止它:

char text1[6] = { 'h', 'e', 'l', 'l', 'o' };
char text2[sizeof "hello"] = { 'h', 'e', 'l', 'l', 'o' };
char text3[] = "hello"; // <--- my personal favourite

是否有特殊原因导致使用单独的字符初始化字符数组不会有空终止符 (0(

原因是因为该语法...

Type name[] = { comma separated list };

。用于初始化任何类型的数组。 不仅仅是char.

"quoted string"语法是非常特定类型的数组的简写,该数组假定需要 null 终止符。

当您指定一组以双引号分隔的相邻字符(字符串文本(时,假定您想要的是一个字符串。C中的字符串意味着一个以null结尾的字符数组,因为这是对字符串(printfstrcpy等(进行操作的函数所期望的。因此,编译器会自动为您添加该 null 终止符。

当您提供大括号分隔、逗号分隔的单引号分隔字符列表时,假定您不需要字符串,但需要您指定的确切字符的数组。因此,不会添加空终止符。

C++继承此行为。