为什么我们需要 C 中的终止字符

Why do we need Termination Character In C

我是 C 编程语言的新手,最近几天正在学习它。我对终止字符的工作原理以及我们为什么需要它有点困惑。当我查看网络上的一些文档时,他们通常会在我们初始化 char 数组时声明最后一个字符必须是“\0”。但是,当我不将它插入到 char 数组的末尾时,它似乎也可以编译并且运行良好。例如:

char test[4] = "test";
printf("%s\n", test );
printf("%lu\n", strlen(test) );

它编译,正确地打印出值,并且还 strlen return 正确的值,这意味着编译器知道 char 数组中的最后一个字符在哪里。那为什么还要在末尾加上'\0'呢。这只是惯例吗?或者还有其他的?

谢谢。

您明确声明 test 为四个字符的数组,因此它是一个四个字符的数组,包含 't'、'e'、's' 和 't' .

printf ("%s") 需要一个 zero-terminated 字符串,strlen 也是如此。您有一个包含四个字符的数组,不包含零,因此将其传递给 printf 或 strlen 是未定义的行为。

由于您的数组后跟未知字节,下一个字节为零可能纯属巧合。如果是这种情况,那么可能是打印了“test”和 strlen() returns 4。但这纯属巧合。

还有可能发生的是您的程序崩溃。或者它打印“testgarbagegarbagegarbage”和 strlen returns 一些大数字。或者您的程序在开发过程中按预期顺利运行,但在第一个付费客户使用时崩溃。

您的代码有未定义的行为,这意味着任何事情都有可能发生。您可以通过声明 char test[] = "test"; 来解决这个问题。这将使 test[] 足够大以容纳四个字符和一个零字节。

编译器知道 statically-declared 个数组的长度。但 C 比那更灵活,它允许你使用更通用的指针。当您通过指针访问数组时,编译器无法知道它指向哪个数组。特别是当函数的参数是字符串时,可以是程序中的任意字符串。

考虑以下代码:

char test1[4] = "test";
char test2[8] = "12345678";
char *test = (rand() % 2 == 0) ? test1 : test2;
printf("%s\n", test);

编译器无法知道 test 的长度——取决于随机选择,它可能是 4 或 8。

您也不能简单地将长度存储在字符串的开头,因为 C 允许您制作指向任何数组元素的指针。考虑:

char test1[8] = "12345678";
char *test = &test[rand() % 8];
printf("%s\n", test);

还有其他语言使用间接来解决这个问题。例如,C++ 有 std::string class,它使用包含长度和指向字符串内容的指针的结构。当您创建子字符串时,它会分配一个新结构并复制数据。但 C 是一种更简单的语言,旨在允许更直接的内存访问。