C 终止字符数组
我试图理解c数组,以及为什么某些类型(比如char)需要空终止符,而其他类型则不需要。以下面三个数组为例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','
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如何检测