所以,我知道字符串的最后一个元素,也就是char数组是NULL,它的值为0。如果我们定义一个包含5个字母的单词的字符串,比如Stack,我们可以按照下面的方法来做。
char word[5] = "Stack";
如果我想访问数组的第一个字母S,我会通过以下方式查找索引0:word[0]
,同样对于最后一个字母k,我会用word[4]
来做索引4。但是这里的一些东西并没有真正进入我的脑海:我们在最初声明数组时使用了数字5。
所以我的第一个问题是,声明中的5是否意味着程序将使用索引0到5,即索引5将包含空字符。
现在,假设我想定义一个int数组,它包含任何内容,但为了这个问题,它应该包含奇数。我通过键入以下内容来实现:
int odds[5] = {1, 3, 5, 7, 9};
这里也是一样,5是否意味着我们将使用索引0到5,索引5将接受NULL值(是的,这是一个愚蠢的问题,因为它是一个int数组,但至少,第五个索引是否包含值0)作为我的第三个问题,为了使它更通用,是否有一个通用规则,即所有数组都将以值0结束?
对于第一个问题,我看了看网络和一些参考资料,并不能真正找到任何答案,点击。
对于第二个,我尝试打印odds[5]的值,它返回0。然后当我尝试打印odds[6]时,它也返回0,所以我怀疑我得到的第一个答案可能是从odds[4]索引的下一个地址中获取的随机值,而不是在初始化时给定的值。
先谢谢你了。
4条答案
按热度按时间jgzswidk1#
如果我们定义一个包含5个字母的单词的字符串,比如Stack,我们可以按照下面的方法来做。
不,你应该做:
甚至更好
结束数组没有“一般规则”,但最常见的方法是将长度作为附加参数。Sentinel值有一个明显的缺点,即必须从可能的值集合中选择一个Sentinel值,然后该值不能用作值。
lndjwyie2#
C中的数组不需要以
NULL
或'\0'
或0
或任何其他特殊值结束。因此char
数组(类型char[]
)也不需要。然而,在C中,如果
char[]
类型的对象不是以char
'\0'
结尾(顺便说一下,它完全等同于0
),则不会被认为是“字符串”。如果缺少了它,代码就会崩溃。顺便说一句,您应该改为编写以下内容之一
(as另一个answerer和一个评论者已经指出了)。第二种形式是推荐的,如果你改变了你的代码,它更不容易出错。
对于
T[N]
数组(其中T
是任何类型),使用的索引是0
到N-1
。如果使用字符串文字初始化
char
数组,则会自动将隐式'\0'
添加到末尾,因为第一行与第二行 * 根据定义 * 等价(编译器自动推断数组大小为
4
)。这种等价性的权威来源是:它们给予了非常相似的例子。
注意:对于historical reasons,你可以写
char str[3] = "hat";
(而不是char str[4] = "hat";
或char str[] = "hat";
),但你真的不应该这样做,因为结果在技术上不是C中的“字符串”。引用一个越界的数组元素是未定义的行为。在你的例子中,
odds[5]
和odds[6]
计算为0
只是偶然的。vuktfyat3#
这里有两个重要的事实:
char
的数组,有一个特殊的约定:它们以空字符结束,空字符肯定是字符串的一部分,但不计入字符串的长度。因此,对于一个字符串(但仅限于字符串),如果字符串的长度为n,则数组的大小必须(至少)为n+1。字符串中的实际字符将从索引0到n-1运行,并且element [n]将是空终止符。
其他类型的数组(比如
int
数组)* 不 * 必须以特殊字符结束。可以这样做,尽管有点不寻常。关于你的问题:
所以,我知道字符串的最后一个元素,也就是char数组是NULL,其值为0。
大多数情况下。字符串的最后一个元素是空字符,即ASCII“NUL”,或者在C中,
'\0'
。在C中,NULL
是一个空 * 指针 *,这是一种不同的野兽。如果我们定义一个包含5个字母的单词的字符串,比如Stack,我们可以按照下面的方法来做。
char word[5] = "Stack";
不,这不会定义一个正确的字符串。要定义一个正确的字符串,你需要做
为空字符留出空间,或者
让编译器为你计算出正确的大小。
但有些事我想不起来我们在最初声明数组时使用了数字5。
对-我的意思是,你感到不安是对的,因为,是的,有些不对劲。
所以我的第一个问题是,声明中的5是否意味着程序将使用索引0到5,即索引5将包含空字符。
不,5意味着数组的索引为0到4,并且没有空字符的空间。
现在假设我想定义一个int数组
好吧,但正如我提到的,在这种情况下没有必要暗示会有终结者。
5是否意味着我们将使用索引0到5,而索引5将采用NULL值?
同样,5意味着你将使用索引0到4来初始化数组的五个值。如果你想使用显式终止符(可能是0或-1),你需要使数组更大,大小至少为6。
是否有一个通用规则,即所有数组都将以值0结束?
不,绝对没有这样的规定。
对于第二个问题,我尝试打印odds[5]的值,它返回0。然后当我尝试打印odds[6]时,它也返回0,所以我怀疑第一个答案
C语言通常不做数组边界检查。所以访问[5]和[6]都是错误的,而且也不知道你会得到什么值--唯一的保证是你 * 不 * 保证会得到错误消息或任何东西。如果你访问一个越界的数组,它通常看起来会工作(你不会得到一个错误消息),有时候这个值甚至看起来是合理的,但不能保证。
slmsl1lt4#
请看下面的代码:
Try it online
看到这个输出“helobye!"了吗?这是因为字符串在内存中直接相邻,中间没有空字节。注意,它可以打印更多,在第二个字符串的末尾“碰巧”有一个空字节,但也可能没有,这将导致打印更多的随机垃圾。
出于这个原因,总是声明一个字符串比它的文本内容长1个字节来存储空字节:
Attempt This Online!
C语言中的字符串就是任何以空结束符结尾的字节数组。
是否所有数组都以0结尾?
不,对于一些字符串函数来说,它们希望传递一个指向以0结尾的数组开始的指针。然而,其他人并不关心。大多数数组函数只是将长度作为额外的参数。一些字符串函数也可以接受长度,如果是这样,就不需要空终止符。
如果省略null终止符而使用字符串函数会怎么样
该函数将读取和写入随机内存,直到它偶然遇到空字节。这被认为是一个“缓冲区溢出”错误,并可能导致,其中包括:
在没有适当限制长度的情况下写入内存甚至更危险。
小心点!