在C中初始化字符串的结尾

时间:2014-03-09 12:08:11

标签: c arrays string

我现在正在学习C,而且我真的没有得到用NULL '\0'字符初始化字符串结尾的区别。以下是本书的例子:

#include <stdio.h>
#include <string.h>

int main(){
    int i;
    char str1[] = "String to copy";
    char str2[20];

    for(i = 0; str1[i]; i++)
        str2[i] = str1[i];
    str2[i] = '\0'; //<====WHY ADDING THIS LINE??

    printf("String str2 %s\n\n", str2);

    return 0;
}

那么,为什么我要添加NULL字符?因为它也没有那条线。另外,如果我使用以下是否有区别:

for (i = 0; str1[i]; i++){
    str2[i] = str1[i];
}

感谢您的时间。

5 个答案:

答案 0 :(得分:2)

您所指的行是为了安全而添加的。当您将值复制到字符串时,您总是希望确保它是空终止的,否则在读取字符串时它将继续超过您希望该字符串结束的点(因为它不知道应该在哪里停止到期缺少空终止符。)

与您发布的备用代码没有区别,因为您只将for语句下面的行分隔为循环,如果您不使用花括号{}

,默认情况下会发生这种情况。

答案 1 :(得分:1)

在C中,字符串的结尾由空字符检测。考虑字符串'abcd'。如果实际二进制文件中的变量在“d”字符后面紧跟下一个变量,则C会认为平台中的下一个字符是该字符串的一部分,您将继续。这称为缓冲区溢出。

你的初始语句允许str2的20个字节通常用20个零填充它,但是,这不是必需的,可能不会发生。另外,我们假设您将15个字符的字符串移动到str2中。因为它以20个零开始,所以这将起作用。但是,假设您将10个字符的字符串复制到str2中。其余5个字符将保持不变,然后您将拥有一个由新的10个字符组成的15个字符的字符串,后跟之前复制的5个字符。

在上面的代码中,for循环表示将str1中的字符移动到str2并指向下一个字符。如果str1中现在指向的字符不为0,则循环返回并再次执行。否则退出循环。现在将空字符添加到str2的末尾。如果你把它遗漏了,str1末尾的空字符将不会被复制到str2,并且你在str2的末尾没有空字符。

这可以表示为

        i = 0;
label:
        if (str1[i] == 0) goto end;
        str2[i] = str1[i];
        i = i + 1;
        goto label;
 end:   /* This is the end of the loop*/

请注意,'\ 0'字符尚未移至str2。

由于C需要括号来显示for的范围,因此只有for后面的第一行才是循环的一部分。如果我有本地范围并且在循环之后丢失,你将无法等待退出循环并使其为0.你将不再有一个有效的i指针告诉你在str2中你需要添加的位置0。

一个例子是C ++或C中的一些编译器,它们允许(语法上)

for (int i = 0; str1[i]; i++)
  {
    str2[i] = str1[i];
  }
str2[i] = 0;

这会失败,因为我会被重置为它进入循环之前发生的任何事情(可能是0),因为它不在循环中。如果在循环之前尚未定义它,则会得到未定义的变量编译器错误。

我看到您修复了缩进,但原始缩进仍然存在,以下注释将适用。

C不仅仅通过缩进工作(例如,Python)。如果是这样,逻辑将如下,它将失败,因为str2将被覆盖为全0。

for (int i = 0; str1[i]; i++)
  {
    str2[i] = str1[i];
    str2[i] = 0;
  }

答案 2 :(得分:0)

'\ 0'用于表示字符串结尾。它不适用于编译器,它适用于库以及可能的代码。 C不能正确支持数组。您可以拥有本地数组,但无法传递它们。如果您尝试只传递起始地址(第一个元素的地址)。所以你可以让最后一个元素变得特殊,例如'\ 0'或者总是传递大小,注意不要搞砸。

例如:

如果您的字符串是这样的:

char str[]="Hello \0 World";

你会告诉我如果你打印str会显示什么? 输出是:

Hello

在字符数组中就是这种情况,因此为了更加安全,最好在字符串的末尾加上'\ 0'。

如果你没有添加'\ 0',可能会打印出一些垃圾值,它会继续打印,直到达到'\ 0'

答案 3 :(得分:0)

您应该只在字符串的末尾添加\0(也称为空字节)。请执行以下操作:

...

for(i = 0; str1[i]; i++) {
    str2[i] = str1[i];
}

str2[i] = '\0'; //<====WHY ADDING THIS LINE??

...

(请注意,我只是添加了大括号以使代码更具可读性,之前令人困惑)

对我来说,这更清楚。你之前做的事情基本上是利用了这样一个事实,即在你运行循环以在i的末尾添加\0后,你声明的整数str2仍然可用。 / p>

字符串在C中的工作方式是它们基本上是指向第一个字符位置的指针,字符串函数(例如您在string.h中可以找到的函数)将读取每个字符,直到它们找到\0(空字节)。它只是标记字符串结尾的约定。

进一步阅读:http://www.cs.nyu.edu/courses/spring05/V22.0201-001/c_tutorial/classes/String.html

答案 4 :(得分:0)

在C中,char []不知道字符串的长度。因此,重要字符'\ 0'(ASCII 0)表示字符串的结尾。你的“For”命令不会复制'\ 0',所以输出是一个字符串&gt; str2(直到找到'\ 0'最后一站)

尝试:

#include <stdio.h>
#include <string.h>

int main(){
    int i;
    char str[5] = "1234";
    str[4] = '5';
    printf("String %s\n\n", str);
    return 0;
}