哪些语言标准允许忽略固定大小数组上的空终止符?

Posted

技术标签:

【中文标题】哪些语言标准允许忽略固定大小数组上的空终止符?【英文标题】:What language standards allow ignoring null terminators on fixed size arrays? 【发布时间】:2016-10-18 02:42:48 【问题描述】:

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

int main()

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

正如Array initialization 中所述:

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

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

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

我希望有人能解释一下。

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

【问题讨论】:

您自己引用了所有标准。是的,它是有效的 C。是的,它是格式错误的 C++。什么不清楚?不,没有人确切知道原因,但普遍认为 C++ 比 C 更严格。 C 和 C++ 是不同的语言。那么为什么你期望它们表现相同呢?一般来说,仅仅让 C 代码在 C++ 中运行是一个坏主意。要么继续使用 C 代码作为单独的模块,要么正确地使用 C++ 功能/库重写。并且显示的代码在 C 中也很糟糕 - 除非您不想要“字符串”。在这种情况下,无论如何使用初始化列表是更好的方法。 @Olaf GNU89 也是一个标准。 让 cmets 保持文明,避免侮辱。我已经清理了这里的东西。 @Olaf “那么你为什么希望它们表现相同呢?”因为 C++ 在设计时就考虑到了兼容性,并且标准委员会试图在可能和适当的情况下保留它。例如,C 标准库是 C++ 标准的一部分;大多数实现对两种语言都使用相同的库二进制文件和头文件源。这是可能的设计特点。偏离这一经验法则的情况很少见,而且委员会成员经常在事后后悔。 【参考方案1】:

您在这里看到的是 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++ 中,您必须为包括空终止符在内的整个字符串文字提供足够的存储空间。

【讨论】:

说明您引用的标准可能是个好主意。 @FUZxxl 刚刚做了。我引用的是现行标准。 看看 C++ 设计原理可能会很有用,但我不知道在哪里可以找到它。 @FUZxxl 很可能是为了安全。通常,您希望使用空终止符使其成为正确的 cstring。 我认为 C++ 希望您将字符串视为字符串,而 C 一直更灵活。【参考方案2】:

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

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

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

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

同上,只是将“有效”改为“无效”。

是否存在在一种语言中有效但在另一种语言中无效的原因?

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

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

【讨论】:

Java 与 C++ 几乎没有任何共同之处。花括号是它们最重要的共同特征。 如果一个结构包含一个精确大小的字符串空间,允许元素初始化为“INIT”比要求它写成'I','N'方便得多,'它'。最好的办法是有一种语法来显式指示没有终止符的字符串,但 C 和 C++ 似乎都没有。 @n.m.它们语法的所有内容实际上都是相同的,但它确实停在那里。

以上是关于哪些语言标准允许忽略固定大小数组上的空终止符?的主要内容,如果未能解决你的问题,请参考以下文章

从固定格式的文本文件批量插入忽略行终止符

忽略 thymeleaf #date.format() 上的语言环境

如何让字符串数组的Contains忽略大小写

如何让字符串数组的Contains忽略大小写

C语言进阶四.动态内存管理

一个经常被忽略的c语言问题