【问题标题】:Why "initializer-string for array of chars is too long" compiles fine in C & not in C++?为什么“字符数组的初始化字符串太长”在 C 中编译得很好而不在 C++ 中编译?
【发布时间】:2015-04-10 14:45:04
【问题描述】:

以下程序在 C 中可以正常编译并出现警告,但在 C++ 中编译失败。为什么?是什么原因?

#include <stdio.h>
int main(void)
{
    char a[5]="Hello";
    a[0]='y';
    puts(a);
    for(int i=0;i<5;i++)
        printf("%c",a[i]);
    return 0;
}

警告:

Warning:[Error] initializer-string for array of chars is too long [-fpermissive] enabled by default

但是如果程序被编译为 C++ 程序,那么 C++ 编译器会给出以下错误:

[Error] initializer-string for array of chars is too long [-fpermissive]

我正在使用 GCC 4.8.1 编译器。

【问题讨论】:

  • C 和 C++ 是不同的语言。
  • 将 Hello 存储为 asciiz 字符串需要 6 个字符
  • 您应该编码 char a[]="Hello"; 以确保有一个终止 0 字节
  • @Milind:C 是宽松的。 C++ 不是。
  • 其实这个问题的前提是不正确的。 两次你都在使用 C++ 编译器,但是一旦它默认使用-fpermissive 编译. -fpermissive 根本不是 GCC C 编译器选项

标签: c++ c string gcc g++


【解决方案1】:

问题在下面一行

char a[5]="Hello";

没有剩余空间来存储终止的空值。

默认情况下,gcc 在启用-fpermissive 选项的情况下不会产生任何错误。所以,它在C编译得很好

根据语言标准的要求,

  • 对于C99 标准,第 6.7.9 章,第 14 段,

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

  • 对于C++11,第 8.5.2 章第 2 段

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

因此,代码使用gcc 编译(带有警告),使用g++ 产生错误。

【讨论】:

  • @meet:它被添加到(或者更确切地说,包含在)字符串文字中,是的。但它不能添加到大小为 5 的数组中,因为这需要第六个元素。
  • @meet 空终止符的空间不存在,因为我们已将数组定义为仅具有 5 chars。
  • @meet:这与强类型无关;只是不同语言的不同规则。允许 C 截断初始化器以适应数组; C++ 不是。有关规则本身,请参阅我的答案。
  • @SouravGhosh:如果你愿意的话。引用语言标准不需要我的许可。
  • 并停止使用这些“先生”的东西;p
【解决方案2】:

C 和 C++ 中的有效字符串应该有一个 \0 终止符和 in

char a[5]="Hello";

空终止符没有空格,a 不是有效字符串。

因此,这可能不是 C 语言中的错误,但在使用 strlen() 和 family 等内置字符串函数时,您肯定会遇到问题。

【讨论】:

  • 这是错误的,用 C 中的字符串字面量的内容初始化一个非空的固定大小字符数组是完全可以的。
【解决方案3】:

因为 "Hello" 的长度为 6 chars,而没有 -fpermissive 的 g++ 不会用它初始化 5 char 数组,但 gcc 会。

【讨论】:

  • 为什么 C 会允许这样做?
  • @meet C 始终保持向后兼容。
【解决方案4】:

简答:因为 C 和 C++ 是不同的语言,具有不同的规则。

长答案:在这两种情况下,原因是数组对于字符串文字来说太小了。字面量由五个可见字符组成,末尾有一个零终止符,因此总大小为 6。

在 C 语言中,您可以使用太长的字符串来初始化数组;多余的字符会被忽略:

C99 6.7.8/14:字符类型的数组可以由字符串字面量初始化,可选用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素。

编译器有用地警告字符串太大,因为它几乎肯定表示错误;但它不能拒绝代码,除非您告诉它将警告视为错误。

在 C++ 中,初始化器不允许大于数组:

C++11 8.5.2/2:初始化器的数量不得超过数组元素的数量。

所以,对于那种语言,编译器应该给出一个错误。

在这两种语言中,当您希望字符数组的大小适合字符串字面量初始化程序时,您可以忽略大小,编译器会做正确的事情。

char a[] = "hello";  // size deduced to be 6

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-10-16
  • 2015-08-21
  • 2016-01-21
  • 2010-12-14
  • 1970-01-01
  • 2014-11-01
  • 1970-01-01
  • 2010-12-16
相关资源
最近更新 更多