为什么 C 语言中的字符串需要以空字符结尾?

24

我想知道为什么会这样。我渴望了解更多关于低级语言的知识,但我只掌握了C语言的基础,就已经让我感到困惑了。

像PHP这样的语言在它们被解释和/或解析时会自动将字符串置为空吗?


相关或可能重复:https://dev59.com/7XM_5IYBdhLWcg3wvFvI - Roger Pate
刚刚发现这个:https://dev59.com/cXI-5IYBdhLWcg3wCz3y - alex
1
有两种常见的文本表示方法:1.指定长度,后跟文本。或使用终止字符。许多数据库使用前者。一个要问自己的问题是,“字符串的结尾如何确定?” - Thomas Matthews
9个回答

31

摘自乔尔的博客文章:

记得C语言中字符串是由一系列字节组成,尾部紧跟一个值为0的空字符。这带来了两个明显的影响:

无法知道字符串何时结束(即字符串长度)除非遍历整个字符串查找末尾的空字符。 字符串中不能包含任何值为0的字节,因此无法像存储JPEG图片这样任意储存二进制数据。 C语言字符串为什么会使用这种方法?这是因为在PDP-7微处理器上,UNIX操作系统和C语言被发明时,使用了ASCIZ字符串类型。ASCIZ代表"以0(零)结尾的ASCII码字符串"

存储字符串的方式只有这一种吗?事实上,这是一种最糟糕的字符串存储方法之一。对于复杂程序、API、操作系统、类库等,建议不要使用ASCIZ字符串。


太好了,谢谢... 还有哪些其他的方法可以使用?谢谢。 - Joe DF
在C99中,是否有一种标准的方法来创建非ASCIZ字符串? - Arc676
1
这是虚构的。我查阅了PDP-7手册,没有找到任何关于ASCIZ、null甚至数据类型的提及。唯一提到ASCII的地方是在输入程序数据中,而零则出现在非字符串位置。有一个TEXT伪指令,但用户可以选择分隔符。
  • http://bitsavers.trailing-edge.com/pdf/dec/pdp7/F-75P_PDP7prelimUM_Dec64.pdf
  • http://www.bitsavers.org/pdf/dec/pdp7/PDP-7_AsmMan.pdf
- Pod
1
事实上,维基百科关于PDP-8的页面上的示例程序展示了空项终止字符串的手动实现。https://en.wikipedia.org/wiki/PDP-8但是我可以在PDP-11材料中找到相关内容。因此,看起来ASCIZ是为支持Unix和C编程语言而将其添加到硬件中的? - Pod

8

想一想内存是什么:一块连续的字节单元,可以填充任何二进制模式。

2a c6 90 f6

一个字符只是其中一种比特模式。它作为字符串的含义由您处理它的方式决定。如果您使用整数视图(或其他类型)查看相同的内存部分,则会得到不同的值。

如果您有一个变量,它是指向内存中一堆字符开头的指针,您必须知道该字符串何时结束以及下一段数据(或垃圾)何时开始。

示例

让我们来看看这个字符串在内存中的情况...

H e l l o , w o r l d ! \0 
^
|
+------ Pointer to string

...我们可以看到,在!字符之后逻辑上字符串就结束了。 如果没有\0(或任何其他确定其结尾的方法),在内存中查找时,我们怎么知道已经完成了该字符串? 其他语言将字符串长度与字符串类型一起传递以解决这个问题。

当我的计算机基础知识有限时,我曾问过这个问题,而这个答案是许多年前对我很有帮助的答案。 我希望它也能帮助其他人。:)


6

C字符串是字符数组,C数组只是指向内存位置的指针,该位置是数组的起始位置。但是数组的长度(或结束)也必须以某种方式表示;在字符串的情况下,使用空终止符。另一种选择是将字符串的长度与内存指针一起传递,或者将长度放在第一个数组位置中,或者其他什么方式。这只是一种约定。

像Java或PHP这样的高级语言会自动透明地存储数组的大小信息,因此用户不必担心它们。


5

C语言本身没有字符串的概念。字符串只是字符数组(对于Unicode等使用wchar的情况也是如此)。

由于这些事实,C语言无法检查字符串的长度,因为没有“mystring->length”这样的东西,也没有设置长度值的地方。找到字符串的结尾的唯一方法是遍历它并检查\0。

C语言中有一些使用结构体的字符串库。

struct string {
    int length;
    char *data;
};

为了消除对\0结尾的需求,但这不是标准C语言。

C++、PHP、Perl等语言有自己的内部字符串库,通常具有单独的长度字段,可以加速某些字符串函数并消除对\0的需求。

其他一些语言(如Pascal)使用称为Pascal字符串的字符串类型,它将长度存储在字符串的第一个字节中,这就是为什么这些字符串的长度限制为255个字符的原因。


4
因为在C语言中,字符串只是通过指向第一个字符的指针访问的字符序列。
指针中没有空间来存储长度,因此需要一些指示来确定字符串的结束位置。
在C语言中,决定使用空字符来表示字符串的结束位置。
例如,在Pascal语言中,字符串的长度记录在指针之前的字节中,这就是为什么Pascal字符串最大长度为255个字符的原因。

1
在C语言中,字符串由分配在连续内存块中的字符数组表示,因此必须有一个指示块末尾的标志(即空字符),或者一种存储长度的方式(例如Pascal字符串,其前缀为长度)。
在像PHP、Perl、C#等语言中,字符串可能具有复杂的数据结构,因此不能假定它们具有空字符。举个牵强的例子,你可以有一种语言,像这样表示字符串:
class string
{
   int length;
   char[] data;
}

但你只能将其视为普通字符串,没有长度字段,因为这可以由语言的运行时环境计算,并且仅在内部使用它来正确分配和访问内存。


1

这是一种约定 - 可以使用另一种算法(例如,在缓冲区开头处放置长度)来实现它。

在汇编等“低级”语言中,有效地测试“NULL”很容易:这可能会使决定使用以NULL结尾的字符串而不是跟踪长度计数器更加容易。


1

它们需要以空字符结尾,这样你就知道它们的长度。是的,它们只是char数组。

像PHP这样的高级语言可能会选择隐藏空字符终止符,或者根本不使用它 - 例如,它们可能会保持一个长度。C语言不会这样做,因为涉及到了额外的开销。高级语言也可能不将字符串实现为char数组 - 例如,它们可以(并且一些语言确实这样做)将其实现为char数组的列表。


0

它们是以空字符结尾的,因为许多标准库函数期望它们是这样的。


3
这是因为C语言规范规定了字符串字面量的编码方式。 - Stephen C
@Stephen C,你是唯一一个说出来的人!非常重要的原因!愚蠢的C字符串...我想要一个带有“Pascal字符串”的C、libc和字符串字面量。 - Prof. Falken

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