21

我们正在将 C 代码转换为 C++。
我注意到以下代码在 C 中定义良好,

int main(){

  //length is valid. '\0' is ignored
  char  str[3]="abc";
}

正如数组初始化中所述:

“如果数组的大小已知,它可能比字符串文字的大小小一,在这种情况下,终止空字符将被忽略。”

但是,如果我要在 C++ 中构建相同的代码,则会收到以下 C++ 错误:

error: initializer-string for array of chars is too long
[-fpermissive]    char  str[3]="abc";

我希望有人能解释一下。

问题:
代码示例在所有 C 语言标准中都有效吗?
它在所有 C++ 语言标准中都无效吗?
是否有一个理由在一种语言中有效但在另一种语言中无效?

4

2 回答 2

17

您在这里看到的是 C 和 C++ 中 cstring 的初始化规则的不同。在 C11 §6.7.9/14 我们有

字符类型的数组可以由字符串文字或 UTF-8 字符串文字初始化,可选地用大括号括起来。字符串文字的连续字节(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。

强调我的

因此,只要数组对于不包括空终止符的字符串足够大,它就有效。所以

char  str[3]="abc";

是有效的 C。在 C++14 中,但在 [dcl.init.string]/2 状态中找到的管理此规则的规则

初始化器的个数不得多于数组元素的个数。

并继续显示以下代码是错误的

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

因此,在 C++ 中,您必须为包括空终止符在内的整个字符串文字提供足够的存储空间。

于 2016-06-16T14:25:53.317 回答
6

代码示例在所有 C 语言标准中都有效吗?

请注意,一次只有一个 ISO 标准有效;C2011 取代了 C99,后者取代了 C89。

不过,我相信它在任何一种标准下都应该是有效的。

它在所有 C++ 语言标准中都无效吗?

同上,只需将“有效”改为“无效”即可。

是否有一个理由在一种语言中有效但在另一种语言中无效?

最有可能的是,它在 C 中保持有效,以免破坏任何依赖该行为的遗留代码。C++ 出现在 C 之后大约十年左右,并试图解决 C 的一些缺点,这是被堵住的漏洞之一。

许多现代编程语言都是对早期语言的迭代和改进;C 是具有类型系统的 B,C++ 是具有 OO 支持和更好的类型安全性的 C,Java 和 C# 是具有较少未定义行为的 C++,等等。

于 2016-06-16T15:32:24.860 回答