C语言中静态字符数组的声明

5

有人能解释一下为什么int array[3] = {1,2,3}可以工作,但是char array[3] = "123"不能工作吗?

它输出了" 123( ( "而不是" 123 "。

它说对于字符数组需要另一个空间来存放空字符,但是数组不是从0开始的吗,所以char array[3]就足够了,因为实际上有4个空间。除非字符数组实际上需要两个空间,一个用于空字符,另一个用于特殊字符。

2个回答

8
int array[3] = {1,2,3}

分配一个数组,最多可以容纳3个整数,您可以使用以下方式访问其中任何一个:

array[0]
array[1]
array[2]

在这里:

char array[3] = "123"

"

"123"由4个字节组成。字符串文字中的字符以NUL终止符结束。但是,您分配了3个字节,最多只能容纳2个字符(+1个NUL终止符)。因此,在使用它初始化数组时,由于没有空间,'\0'未被写入。

当您在printf中使用%s打印时,它会引发未定义行为,因为%s会打印直到NUL终止符。因此,printf会继续从无效的内存位置读取值,直到出现'\0'。这样做可能会导致任何事情发生。您可能会看到随机垃圾输出、崩溃、分段错误等。基本上,即使看起来已经按预期“工作”,您也永远不应该依赖这种行为。

但是数组不是从0开始吗?

是的

那么char array[3]就足够了,因为实际上有4个空间

错了。对于char array[3],有效的索引为

"
array[0]
array[1]
array[2]

访问 array[3] 是错误的,会引起未定义行为


通过使用下面的方法修复此问题:

char array[4] = "123";

或者更好的方法:
char array[] = "123";

空括号告诉编译器确定数组的大小。

1
访问array[3]肯定是未定义的行为,但是array本身的初始化是明确定义的,因此上面的array初始化等同于char array[] = {'1','2','3'};。不需要空终止符的空间。另一方面,char array[3] = "1234";是未定义的,因为“没有初始化器可以尝试为未包含在正在初始化的实体中的对象提供值”(C11草案N1570 6.7.9p2),这意味着array太小,无法容纳4个元素{'1','2','3','4'}。 N1570的6.7.9p32表达了预期的行为。 - user539810
@ChronoKitsune,我不知道!所以'\0'没有被提供? - Spikatrix
1
如果有足够的空间,就会包括空终止符,但这并不是必需的。从技术上讲,任何多余的元素都会被初始化为0,因此即使没有添加字符串字面值的空终止符,如果数组长度大于字符串字面值的长度,数组仍将被终止。 - user539810

5
在C语言中声明一个数组时,char array[3]将得到3个字符,而不是像你在问题中建议的那样得到4个。你需要为字符串末尾的空字符留出空间,所以在这种情况下你需要char array[4]。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接