为什么C中的字符串需要以null结尾?

只是想知道为什么会这样。 我渴望了解更多有关低级语言的知识,而且我只是进入C的基础知识,这已经让我感到困惑。

像PHP这样的语言会在解释和/或解析时自动为null终止字符串吗?

来自Joel关于这个主题的优秀文章:

记住字符串在C中的工作方式:它们由一串字节后跟一个空字符组成,其值为0.这有两个明显的含义:

没有办法知道字符串结束的位置(即字符串长度),而不是通过它,在最后查找空字符。 您的字符串中不能包含任何零。 因此,您无法在C字符串中存储任意二进制blob,如JPEG图片。 为什么C字符串以这种方式工作? 这是因为发明了UNIX和C编程语言的PDP-7微处理器具有ASCIZ字符串类型。 ASCIZ的意思是“最后用Z(零)的ASCII”。

这是存储字符串的唯一方法吗? 不,实际上,这是存储字符串的最糟糕方式之一。 对于非平凡的程序,API,操作系统,类库,您应该避免像瘟疫这样的ASCIZ字符串。

C字符串是字符数组,C数组只是指向内存位置的指针,内存位置是数组的起始位置。 但也必须以某种方式表达数组的长度 (或结束); 在字符串的情况下,使用空终止。 另一种选择是以某种方式携带字符串的长度与存储器指针一起,或者将长度放在第一个数组位置,或者其他什么。 这只是一个惯例问题。

Java或PHP等高级语言可以自动,透明地存储数组的大小信息,因此用户无需担心它们。

因为在C字符串中只是一个字符序列访问viua指向第一个字符的指针。

指针中没有空间来存储长度,因此您需要指示字符串结尾的位置。

在C中,决定用空字符表示。

例如,在pascal中,字符串的长度记录在指针前面的字节中,因此pascal字符串的最大长度为255个字符。

C本身没有字符串的概念。 字符串只是字符数组(或unicode等的wchars)。

由于这些事实,C无法检查字符串的长度,因为没有“mystring-> length”,因此没有设置长度值。 找到字符串结尾的唯一方法是迭代它并检查\ 0。

C的字符串库使用类似的结构

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

删除\ 0-termination的需要,但这不是标准C.

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

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

想想内存是什么:一个连续的字节大小的单元块,可以用任何位模式填充。

 2a c6 90 f6 

字符只是其中一种位模式。 它作为一个字符串的含义取决于你如何对待它。 如果您查看内存的相同部分,但使用整数视图(或其他类型),您将获得不同的值。

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

我们来看看内存中的这个字符串……

 H ello , world ! \0 ^ | +------ Pointer to string 

…我们可以看到字符串在逻辑上结束了! 字符。 如果没有\0 (或任何其他方法来确定它的结束),我们怎么知道在通过内存寻找我们已经完成该字符串? 其他语言带有字符串长度和字符串类型来解决这个问题。

当我对计算机的基础知识有限时,我问了这个问题, 是多年前可以帮助的答案。 我希望它也可以帮助别人。 🙂

这是一种约定 – 人们可以用另一种算法实现它(例如缓冲区开头的长度)。

在诸如汇编程序之类的“低级”语言中,很容易有效地测试“NULL”:可能很容易决定使用NULL终止字符串而不是跟踪长度计数器。

它们需要以空值终止,以便您知道它们有多长。 是的,它们只是char的数组。

像PHP这样的高级语言可能会选择隐藏空终止或根本不使用它 – 例如,它们可能会保持长度。 由于涉及的开销,C不会这样做。 高级语言也可能不会将字符串实现为char数组 – 例如,他们可以(有些人)将它们实现为char数组的列表。

在C中,字符串由在连续的内存块中分配的字符数组表示,因此必须有一个指示块结尾的指示符(即空字符),或者存储长度的方式(如Pascal字符串)它们以长度为前缀)。

在PHP,Perl,C#等语言中。字符串可能有也可能没有复杂的数据结构,因此您不能假设它们具有空字符。 作为一个人为的例子,你可以使用一种代表字符串的语言:

 class string { int length; char[] data; } 

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

它们是空终止的,因为有很多标准库函数需要它们。