当固定大小的字符数组未留足空间来存放空终止符时,编译器没有报错。

16

假设我有以下几个 C 字符数组:

char okaysize4[5] = "four";   // line 5
char toosmall4[4] = "four";   // line 6
char toosmall3[3] = "four";   // line 7

使用gcc 4.4.7编译时,我遇到了以下错误:

array.c:7: warning: initializer-string for array of chars is too long

这个错误对于第7行是预期的,因为我试图把五个字符("four" + \0)塞进一个3元素的数组里。 而对于第5行没有错误是预期的,因为这个5元素的数组足够大。

然而,我惊讶的是第6行没有类似的错误。在toosmall4中被初始化的是一个未终止的字符串,这可能会引起各种麻烦。

我的理解是c字符串字面值"four"应该有五个字符长度,因为有空字符结束符。实际上,sizeof("four")为5。那么为什么编译器不会在这里报错呢?

有没有一些方法可以更改我的声明/定义/初始化,以便在这种情况下标记一个错误?

2个回答

19
这是第六行的预期行为,来自于draft C99 standard6.7.8Initialization 段落的第14句话(我强调的):

字符类型的数组可以通过字符字符串字面值进行初始化,可选地用大括号括起来。字符字符串字面值的连续字符(包括终止空字符(如果有空间或数组大小未知))初始化数组的元素。

在C11草案标准中,具有类似措辞的相关部分为第6.7.9节的第14段,正如C FAQ所述:

因此,该数组不是真正的C字符串,不能与strcpy、printf的%s格式等一起使用。

正如Keith Thompson所指出的,C++更加严格,草案C++标准中的相关部分如下:

There shall not be more initializers than there are array elements. [ Example:

char cv[4] = "asdf"; // error

is ill-formed since there is no space for the implied trailing ’\0’. —end example ]


这个特性自古以来就存在于C语言中。 - Jim Balter

5

合法,toosmall4不是字符串,但是它是一个有效的字符数组(没有终止的空字符)。

参考: C FAQ


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