为什么只有char数组以空字符结尾?

10

为什么字符数组需要以NULL结尾? 例如,为什么整数数组不需要在末尾添加分隔符?


5
你会为一个int数组使用什么作为分隔符? - congusbongus
4
字符数组就像其他数组一样,并不需要以空字符结尾。 - Naveen
@congusbongus:这实际上是一个很好的修辞问题。我将扩展初学者的暗示后果:使用0在ASCII编码方面是有意义的。因为它是“null char”的代码。另一种类型可以用于编码字符串。例如,wchar_t将遵循相同的编码约定。 int很少用于保存字符串,因此什么值可以用作“null”?通常没有。特别不是0,因为它可能是您想要存储在数组中的正常内容。 - v.oddou
2
NULL是一个宏,它会扩展为一个空指针常量。终止C字符串的空字符'\0'不是同一件事情。 - Keith Thompson
6个回答

7

char[] 不必以 NUL 结尾。这是一种约定,用于将 char 数组用作字符串时。您可以在没有终止符的情况下为自己的目的使用 char[]。


“character strings” 精确地说。这个约定被 stdlib/string.h 视为标准,用于处理字符串的标准函数。为了实用性,许多处理字符串的人都采用了这个约定。此外,C 标准本身也会对字符串字面量进行空终止。 - v.oddou
2
@v.oddou:确切地说是字符串。该术语在C标准的7.1.1中定义:“字符串是由第一个空字符终止并包括在内的一系列连续字符。” - Keith Thompson
对我来说,问题实际上是“为什么我们需要在char数组末尾添加一个空字符来表示结束呢?这解决了一个不存在的问题,即‘我不知道如何找到数组的结尾’…” 我认为答案是“您可以在静态数组上使用'sizeof',但不能在动态数组上使用,因此以NULL字符结尾是一种惯例,在许多字符串函数中得到利用…”-请参见https://dev59.com/x3DYa4cB1Zd3GeqPEMUL(或其重复项) - Simon
@john 对不起,我稍微误读了你的评论,我想我当时认为“char array”和“string”这个术语是可以互换的,但是“string”有一个特定的含义...你可能真的需要一个单独字符的数组,而字符串则被假定为连续使用,并且因此有利于以空字符结尾...或者类似这样的东西? - Simon
@Simon 我认为你说得很对。正如Keith Thompson(上面)所说,“string”一词在C标准中有着特定的含义。并非所有的char数组都是字符串,至于所有的字符串是否都是char数组,我会让语言专家们争论(我认为它们是,但有一个NUL终止的限制)... - John3136
显示剩余2条评论

7
这是一个方便的问题。
ISO C标准第7.1.1节这样定义了一个字符串:
“字符串”是由第一个空字符终止并包括在内的一系列连续字符。
有许多可能的表示字符字符串的方式,例如使用计数和数组,或使用计数和指针。对于C语言,使用空终止符号是一种方便的方式,用于字符串字面值和处理字符串的标准库函数。
这很方便,因为空字符实际上并没有被用于其他任何事情。它不可打印,也不是控制字符,具有某些定义的显示行为,例如以某种特定的方式移动光标。
您可以拥有几乎任何类型的数组,但使用零值来标记序列的约定并不像其他类型那样方便。对于整数或浮点类型,零是您可能希望将其作为正常数据存储在数组中的有效值。
指针确实有一个可用于标记序列结尾的特殊值:空指针NULL。事实上,有时会以此方式使用。C程序的命令行参数作为指向字符串的指针序列传递;该序列的长度由argc的值指示,并由终止空指针标记。还请参阅类Unix系统上的environ指针和exec*()函数。
(但是对于某些应用程序,空指针也可以是有效值,因此不能用作终止符。)
字符字符串操作是C语言和库的重要部分,因此对于如何表示字符字符串,有一个约定是有意义的。该约定不适用于其他类型的数组。
(顺便说一下,重要的是要记住,NULL是扩展为null指针常量的宏。使用名称NULL来引用null字符'\0'是不正确的。根据上下文,两者都可以在C源代码中表示为常量0,但它们是非常不同的东西。)

0

你不需要使用 Cchar[] 来进行空终止,而是需要使用 string。因为在 C 中,string 意味着一个以 null 为空结尾的字符数组,而 \0 null 终止符 告诉库字符串的结束位置。

为什么?

因为最初的 C 是一种基本语言,抽象程度较低,没有将 string 作为数据类型。在 C 中,string 只是一组 char 的集合。

更明确地说,技术上并没有叫做 string 的数据类型,它只是为了方便程序员使用而实现的外观,是一个常用的高级概念,通常使用基本数据类型 char 实现。


1
不,字符串不是指向char[]的指针;它是字符序列。你可以有一个指向字符串的指针;这个指针本身并不是字符串。 - Keith Thompson
谢谢指正,已经纠正。我在一本书中读到过这个问题,但是目前不太记得了,如果我找到了会指出来的。不过,当我引用一个字符串a char array时,它是如何知道数组的第一个元素在哪里的呢? - SajjadHashmi
字符串 str = "我怎么知道?",printf(str); str 如何知道 H 即 char[] 的起始位置在哪里? - SajjadHashmi
2
在 C 语言中没有 string 类型。如果你的意思是 char *str = "How do I know?",那么 str 指向 'H'。 如果你的意思是 char str[] = "How do I know?",那么 str 是一个数组;由于它是数组类型的表达式,在大多数情况下将被隐式转换为指向数组第一个元素的指针,也就是这里的 'H'。请参阅 comp.lang.c FAQ - Keith Thompson
所以我写的是“技术上没有叫做字符串的数据类型”,而“字符串”实际上是指向“字符”的指针?就像“str”指向“H”一样? - SajjadHashmi
显示剩余2条评论

0

我经常使用以NULL结尾的intchar*struct等数组,而且我也在其他人的代码中看到了相同的解决方案。这是一个非常普遍的现象 :)

但是:至少在语言核心中没有针对NULL结尾字符串的语言指令,尽管一些标准C库使用它(主要在<string.h>中)。


0
在C语言中,字符串的概念被表示为以NUL结尾的char数组。因此,并不是每个char数组都以NUL结尾;你可能有一个不代表字符串的这样的数组。你可能有一个char数组,其中包含嵌入式NUL字节,这些字节不表示终止符(因为该数组包含任意二进制数据,而不表示字符串)。
通常情况下,你不会看到其他数组类型的终止符(哨兵值),因为一般来说,你会使用什么值?哨兵值需要是不用于数组其他元素的值。但是,在某些特殊情况下,你会看到哨兵值;例如,对于指针数组(例如main()函数的argv参数),有时使用NULL作为哨兵值是合理的。
关于为什么C字符串是以NUL结尾的(而不是Pascal风格的字符串),这是语言作者选择的设计。每种方法都有权衡。还可以参考为什么要使用以空字符结尾的字符串的原因?

-1
在int数组中,数组元素永远不会作为字符串一起使用。然而,char数组则不同。通过以null结尾字符来终止一个字符数组,您就可以将其用作字符串。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接