Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 终止字符数组_C - Fatal编程技术网

C 终止字符数组

C 终止字符数组,c,C,我试图理解c数组,以及为什么某些类型(比如char)需要空终止符,而其他类型则不需要。以下面三个数组为例 int v1[] = {1, 2, 3}; char v2[] = "hello"; char v3[] = {'h', 'e', 'l', 'l', 'o', '\0'} c如何“知道”v1何时结束,但它需要字符数组中的“\0”才能知道v1何时结束?是什么使字符与数字不同,要求在结尾处使用某种假字符来告诉程序它已完成?例如,如果不是写charv3[]={'h','e','l','l','

我试图理解c数组,以及为什么某些类型(比如char)需要空终止符,而其他类型则不需要。以下面三个数组为例

int v1[] = {1, 2, 3};
char v2[] = "hello";
char v3[] = {'h', 'e', 'l', 'l', 'o', '\0'}

c如何“知道”v1何时结束,但它需要字符数组中的“\0”才能知道v1何时结束?是什么使字符与数字不同,要求在结尾处使用某种假字符来告诉程序它已完成?例如,如果不是写
charv3[]={'h','e','l','l','o','\0'}
,而是写为
charv3[]={'h','e','l','l','o'}
(当我使用For循环检测它的结尾时,除了越界之外)。

C中的字符串是数组的特例。具体来说,它们是以null结尾的
char
数组

在这种情况下:

char v2[] = "hello";
数组
v2
用字符串常量
“hello”
初始化。这个常量的大小是6,所以数组的大小是6。这也意味着数组包含一个字符串,可以传递给需要字符串的函数

为此:

char v3[] = {'h', 'e', 'l', 'l', 'o'}

v3
是大小为5的
char
数组,因为它由5个元素初始化。它不是字符串,因为它不是以null结尾的。

C中有
字符串的概念,因为它便于文本处理。根据通用协议,C中的字符串以“\0”字节结尾,以标记字符串的结尾。字符串可以声明为:

char str[] = {'h', 'e', 'l', 'l', 'o', '\0'}
但为了让生活更轻松,这里有一个常用的缩写:

char str[] = "hello";

您可能认为后者只是前者的一个更易于键入的版本。

问题不在于数组包含或不包含什么,也不在于编译器“知道”数组大小。问题很简单:一旦创建了数组,我们将如何使用它,特别是我们将如何记住(我们编写和使用的代码如何知道)数组有多大

虽然编译器在编译代码时总是知道每个数组的确切大小,但这是编译时的事情,而不是运行时的事情。该语言没有提供任何机制在运行时告诉我们任意数组有多大。因此,这取决于我们(可以这么说)来解决

这就是零终止的原因。这是C语言中的一个惯例(但非常重要!),当您有一个类型为
char
的数组,并且当您将该数组用作“字符串”,该字符串必须始终由
\0
终止。每个处理字符串的C函数——标准C库中的预定义函数,以及我们可能编写的任何字符串操作函数——每个函数都依赖于此约定。如果您有一个非空终止的
char
数组,并且如果您将其交给字符串处理函数,则该函数在试图计算字符串有多大时,将直接运行到末尾,并且会产生各种未定义的结果

与使用像
\0
这样的“哨兵值”来终止数组不同,跟踪数组大小的另一种主要方法是在一旁使用一个单独的“count”变量。这就是我们可能通过使用

int v1size = 3;
或许

int v1size = sizeof(v1) / sizeof(v1[0]);

c如何“知道”v1何时结束,但它需要字符数组中的“\0”才能知道v1何时结束

编译器完全知道每个数组有多大。(是编译器将
\0
添加到
v2
,所以它必须知道!)真正的问题是,
printf
如何知道

如果。。。它被写成
charv3[]={'h','e','l','l','o'}
(当我使用for循环来检测它的结束时,除了越界之外)

除了您(和
printf
,和
strlen
,和
strcpy
,以及其他所有人)在尝试检测结束时会出现越界错误(或等效错误)之外,不会发生任何事情


另请参见。

在使用C语言时,他们做出了一个设计决策,即不在生成的可执行文件中自动存储数组大小。这就是这一切的根源

你把编译器知道的和运行时库知道的混为一谈。在所有3个示例中,编译器确切地知道每个数组有多大以及它包含多少个元素,这可以在编译时确定

但是,这些信息仍然是编译器内部的,并且数组的大小不存储在可执行文件中。因此数组大小不能自动传递到运行时库,如
string.h
,因为它不存储在任何地方

相反,库函数得到一个
char*
,它只是指向数组第一个元素的指针,没有提供其他信息。为了知道有效数据的结束位置,因此需要一个空终止符


类似地,如果将数组语法替换为指针,
char*p=“hello”,则编译器将无法知道
p
指向的内容的大小。如果您使用
sizeof(p)
您只会得到指针的大小,而不是它所指向的数组。

拥有一个字符数组而不是以
\0
结尾是完全有效的,那么它就不被称为字符串,在
string.h
中使用
str*
函数是不安全的。空终止符仅用于C字符串函数,如strlen、strcpy。。。如果您将它用作数组,那么显然不需要空终止。没有提到的是,您可以在数组中的任意点空终止字符串,而不仅仅是在最后一个元素,这样您就可以存储不同长度的字符串。知道数组长度实际上并不能告诉您字符串的长度。谢谢您的解释。那么,为什么非字符数组不需要这样做呢?C如何检测