C中数组中的终止NULL

C中数组中的终止NULL,c,string,C,String,我有一个简单的问题为什么有必要考虑在AN中的终止空值 字符数组(或简单的字符串),而不是整数数组。所以当我想要一个字符串包含20个字符时,我需要声明charstring[21]。当我想要声明一个包含5个数字的整数数组时,那么int-digits[5]就足够了。原因是什么?字符数组不一定必须是21个元素。只有遵循(几乎总是假定的)约定,即二十个字符后面跟一个空终止符时,才有必要这样做。整数和其他数组中的终止符通常没有这样的约定。如果您不想用NULL来终止char数组,但是当使用它们来表示字符串时,

我有一个简单的问题
为什么有必要考虑在AN中的终止空值
字符数组(或简单的字符串),而不是整数数组。所以当我想要一个字符串包含20个字符时,我需要声明
charstring[21]。当我想要声明一个包含5个数字的整数数组时,那么
int-digits[5]就足够了。原因是什么?

字符数组不一定必须是21个元素。只有遵循(几乎总是假定的)约定,即二十个字符后面跟一个空终止符时,才有必要这样做。整数和其他数组中的终止符通常没有这样的约定。

如果您不想用
NULL
来终止
char
数组,但是当使用它们来表示字符串时,您需要这样做,因为C使用来表示它的字符串。当您使用对字符串进行操作的函数(如
strlen
表示字符串长度或使用
printf
输出字符串)时,这些函数将读取数据,直到遇到
NULL
。如果没有,则可能会遇到缓冲区溢出或类似的访问冲突/分段错误问题


简而言之:这就是C表示字符串数据的方式。

字符串中的空终止的目的是让解析器知道何时停止遍历字符数组

因此,当您将
printf
%s
格式字符一起使用时,它实际上是这样做的:

int i = 0;
while(input[i] != '\0') {
   output(input[i]);
   i++;
}

这个概念通常被称为哨兵(sentinel)。只有按照惯例,C字符串以ascii nul字符结尾。(这实际上与NULL不同。)

如果你喜欢,你可以用一个NUL字节开始你的字符串,或者在字符串的中间随机包含NUL字节。然后,您将需要自己的库


所以答案是:所有数组都必须为其所有元素分配空间。您的“20个字符的字符串”只是一个21个字符的字符串,包括nul字节。

这不是要声明一个更大的数组,而是我们如何选择在C中定义字符串

按照惯例,C字符串被认为是以最后一个NUL字符结尾的一系列字符,如您所知。这是以解释
“string literals”
的形式融入语言的,并被所有标准库函数采用,如
strcpy
printf
等。每个人都同意,这就是我们在C中处理字符串的方式,字符用于告诉这些函数字符串停止的位置


从另一个角度来看你的问题,你不在整数数组中做类似的事情的原因是因为你有其他方法知道数组的长度,或者你用它传递一个长度,或者它有一些假定的大小。字符串可以在C中以这种方式工作,或者具有其他一些结构,但它们没有——贝尔实验室的人员认为“字符串”将是一个标准的字符数组,但始终具有终止NUL,以便您知道它的结尾。(当时这是一个很好的折衷办法。)

字符串(或字符数组)末尾需要空终止符,因为:

  • 大多数标准库字符串函数都希望有空字符。它被放在那里,而不是传递一个显式的字符串长度(尽管有些函数需要这样做)
  • 根据设计,
    NUL
    字符(ASCII 0x00)用于指定字符串的结尾。因此,当读取ASCII文件或流时,它也用作EOF字符

  • 从技术上讲,如果您使用自己的编码函数进行自己的字符串操作,则不需要空终止符;您只需要跟踪字符串的长度。但是,如果您使用的只是标准化的任何东西,那么它将是预期的。

    由于与其他约定相比如何实现的技术原因

    原因是它是原始实现者的设计选择。以null结尾的字符串提供了一种将数组传递到函数而不传递大小的方法。对于整数数组,必须始终传递大小。Ints语言的惯例没有什么了,你可以不用空终止符重写c中的每个字符串函数,但你必须始终跟踪数组大小。

    事实上,如果你不想,你不必NUL终止你的字符串! 唯一的问题是必须重写所有字符串库,因为它们依赖于它们。如果您想使用它们的功能,只需按照库所期望的方式进行操作

    就像如果我想和你的女儿约会,我必须在午夜把她带回家一样——只是和图书馆(或者在这个例子中,是父亲)达成协议