问题 为什么我们需要在C中的字符数组末尾添加'\ 0'(null)?


为什么我们需要在C中的字符数组末尾添加'\ 0'(null)? 我在K&R 2(1.9字符数组)中读到过它。书中找到最长字符串的代码如下:

#include <stdio.h>
#define MAXLINE 1000
int readline(char line[], int maxline);
void copy(char to[], char from[]);

main() {
    int len;
    int max;
    char line[MAXLINE];
    char longest[MAXLINE];
    max = 0;
    while ((len = readline(line, MAXLINE)) > 0)
        if (len > max) {
            max = len;
            copy(longest, line);
        }
    if (max > 0)
        printf("%s", longest);
    return 0;
}

int readline(char s[],int lim) {
    int c, i;
    for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
        s[i] = c;
    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0'; //WHY DO WE DO THIS???
    return i;
}

void copy(char to[], char from[]) {
    int i;
    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}

我的问题是为什么我们将字符数组的最后一个元素设置为'\ 0'? 没有它,该程序工作正常...... 请帮帮我...


2906
2017-12-16 18:15


起源

\0 表示字符串的结尾 - jbowes
局部变量未在C中初始化。因此,局部变量 line 你不写信的地方有垃圾。如果垃圾发生了 0 然后你的程序将工作,而无需显式写入null。但是,如果你再做一次 readline 进入 line 变量,并使这一行比第一行更短,你会看到第二行结束时第一行的残余 line。在末尾写入空字符将阻止这种情况。 - Erik Eidt


答案:


你需要结束C字符串 '\0' 因为这就是库如何知道字符串结束的位置(在你的情况下,这就是 copy() 功能期望)。

没有它,该程序工作正常......

没有它,你的程序就有了 未定义的行为。如果程序碰巧做了你期望它做的事情,你就是幸运的(或者说,不幸的是,因为在现实世界中未定义的行为将选择在最不方便的情况下表现出来)。


14
2017-12-16 18:17



但没有它,该程序工作正常...... - ShuklaSannidhya
@ SandyLee_user53167这次你很幸运:) - Maroun
尝试在其上调用strcpy。 - Jeremy D
如果从这个程序中省略,是否正确? - ShuklaSannidhya
@ SandyLee_user53167 copy 代码中的函数运行直到它看到 \0 字符。 - rohit89


在c“string”中表示以null结尾的字符数组。将其与pascal字符串进行比较,这意味着最多255个字符,前面是一个表示字符串长度的字节(但不需要终止)。

每个appraoch都有它的优点和缺点。


1
2017-12-16 18:24



Nota bene:同时,流行的(好的,或多或少)语言Delphi引入了各种类型的字符串,其中只有一个具有255个char限制。所有其他(ansi,unicode,wide等)都有(我认为)4 GB的限制。 - alzaimar
@alzaimar嗯,肯定比比较受欢迎 本身 这几天帕斯卡尔。我自己也不知道。无论哪种方式,程序员都可以选择他或她的毒药,这总是很好。 - dmckee


特别是字符串指针指向没有长度已知的字符数组是唯一的方法 NULL 终结符将确定字符串的长度。

关于NULL终止的讨论很棒 链接


1
2017-12-16 18:20





因为C将字符串定义为 由第一个空字符终止并包括第一个空字符的连续字符序列

基本上,C的作者可以选择将字符串定义为字符序列+字符串的长度,或者使用魔术标记来分隔字符串的结尾。

有关该主题的更多信息,我建议您阅读本文:

Poul-Henning Kamp的“最昂贵的单字节错误” http://queue.acm.org/detail.cfm?id=2010365


0
2017-12-16 18:34





你实际上已经在这里自己写了答案:

void copy(char to[], char from[]) {
    int i;
    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}

此函数中的循环将继续,直到它遇到数组中的'\ 0' 。如果没有终止零,则循环将继续执行未知数量的步骤,直到遇到零或无效的存储区域。


0
2017-12-16 18:50





真的,你这样做  需要通过\ 0结束字符数组。它是char *,或者需要由它结束的字符串的C表示。

至于数组,你必须添加\ 0  如果你想将它转移到字符串(由char *表示),它的结尾。

另一方面,如果要将其作为char *处理,并且计划在其上使用char *函数,则需要在数组的末尾使用\ 0。


0
2017-12-17 11:26





'\0' 在数组中表示字符串的结尾,这意味着该字符后面的任何字符都不被视为字符串的一部分。这并不意味着它们不是字符数组的一部分。也就是说,我们仍然可以通过索引来访问这些字符,但是当我们向这个字符数组调用与字符串相关的东西时它们就不合适了。

要使字符串格式正确并且能够与字符串函数一起正常工作,它必须是以null结尾的字符数组。如果没有NULL,当我们在字符数组上调用字符串函数时,程序会显示未定义的行为。尽管我们大多数时候都可能对结果感到幸运,但它仍然是一种未定义的行为。


0
2017-12-12 07:28





它是字符串终止符号,当遇到这种情况时,编译器会知道你的字符串已经结束。


-1
2017-12-16 20:07



编译器与此无关。它仅在运行时进行评估。 - njzk2