【发布时间】:2010-12-27 05:59:12
【问题描述】:
我有一个简单的问题。
为什么有必要考虑一个终止空值
字符数组(或简单的字符串)而不是整数数组。所以当我想要一个包含 20 个字符的字符串时,我需要声明 char string[21];。当我想声明一个包含 5 位数字的整数数组时,int digits[5]; 就足够了。这是什么原因?
【问题讨论】:
我有一个简单的问题。
为什么有必要考虑一个终止空值
字符数组(或简单的字符串)而不是整数数组。所以当我想要一个包含 20 个字符的字符串时,我需要声明 char string[21];。当我想声明一个包含 5 位数字的整数数组时,int digits[5]; 就足够了。这是什么原因?
【问题讨论】:
如果你不想用NULL来终止一个char数组,但是当你用它们来表示一个字符串时,你需要这样做,因为C使用null-terminated strings来表示它的字符串。当您使用对字符串进行操作的函数时(如strlen 用于字符串长度或使用printf 输出字符串),这些函数将读取数据直到遇到NULL。如果不存在,那么您可能会遇到缓冲区溢出或类似的访问冲突/分段错误问题。
简而言之:这就是 C 表示字符串数据的方式。
【讨论】:
字符串(或字符数组)末尾需要空终止符,因为:
NUL 字符 (ASCII 0x00) 用于指定字符串的结尾。因此,在从 ASCII 文件或流中读取时,它也用作 EOF 字符。从技术上讲,如果您使用自己的编码函数进行自己的字符串操作,则不需要 空终止符;您只需要跟踪字符串的长度即可。但是,如果您使用任何标准化的东西,它会期望它。
【讨论】:
只有按照惯例,C 字符串以 ascii nul 字符结尾。 (这实际上与 NULL 不同。)
如果您愿意,您可以以 nul 字节开始您的字符串,或者在字符串中间随机包含 nul 字节。然后,您将需要自己的库。
所以答案是:所有数组都必须为其所有元素分配空间。您的“20 字符串”只是一个 21 字符的字符串,包括 nul 字节。
【讨论】:
原因是它是原始实现者的设计选择。以空结尾的字符串为您提供了一种将数组传递给函数而不传递大小的方法。对于整数数组,您必须始终传递大小。语言的 Ints 约定仅此而已,您可以在不使用 null 终止符的情况下重写 c 中的每个字符串函数,但您始终必须跟踪数组大小。
【讨论】:
字符串中空终止的目的是让解析器知道何时停止遍历字符数组。
因此,当您将printf 与%s 格式字符一起使用时,它本质上是这样做的:
int i = 0;
while(input[i] != '\0') {
output(input[i]);
i++;
}
这个概念通常被称为哨兵。
【讨论】:
这不是关于声明一个更大的数组,而是关于我们如何选择在 C 中定义字符串。
如您所知,按照惯例,C 字符串被认为是由最终 NUL 字符终止的一系列字符。这以解释 "string literals" 的形式融入到语言中,并被所有标准库函数(如 strcpy 和 printf 等)采用。每个人都同意这就是我们在 C 中处理字符串的方式,并且该字符用于告诉那些函数字符串在哪里停止。
反过来看你的问题,你不在你的整数数组中做类似的事情的原因是因为你有其他方法知道数组有多长——或者你传递一个长度,或者它有一些假定的大小。字符串可以在 C 中以这种方式工作,或者具有其他一些结构,但他们没有——贝尔实验室的人决定“字符串”将是一个标准的字符数组,但会总是有终止的 NUL 所以你会知道它在哪里结束。 (当时这是一个很好的权衡。)
【讨论】:
字符数组不是绝对必须有 21 个元素。仅当您遵循(几乎总是假定的)约定时,才需要二十个字符后跟空终止符。整数和其他数组中的终止符通常没有这样的约定。
【讨论】:
由于与其他约定相比,C Strings 的实现方式存在技术原因
【讨论】:
实际上 - 如果你不想,你不必 NUL 终止你的字符串! 唯一的问题是您必须重新编写所有字符串库,因为它们依赖。如果您想使用它们的功能,只需按照库所期望的方式进行操作即可。
就像如果我想和你女儿约会,我必须在午夜带她回家一样——只是与图书馆(或者在这种情况下,是父亲)达成协议。
【讨论】: