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

ale*_*lex 20 c string null-terminated

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

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

Max*_*keh 28

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

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

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

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


ale*_*lex 8

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

2a c6 90 f6
Run Code Online (Sandbox Code Playgroud)

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

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

例子

让我们看看内存中的这个字符串......

H e l l o , w o r l d ! \0 
^
|
+------ Pointer to string
Run Code Online (Sandbox Code Playgroud)

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

当我对计算机的基础知识有限时,我问了这个问题,而这个答案在很多年前就会有所帮助。我希望它也对其他人有帮助。:)


Joo*_*kka 7

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

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


Pau*_*ams 5

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

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

在 C 中,决定这将由空字符表示。

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


Mor*_*dur 5

C本身没有字符串的概念.字符串简单字符的阵列(或wchars为Unicode和这样).

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

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

struct string {
    int length;
    char *data;
};
Run Code Online (Sandbox Code Playgroud)

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

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

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