为什么 "initializer-string for array of chars is too long" 在 C 中编译良好而不在 C++ 中编译?

Why "initializer-string for array of chars is too long" compiles fine in C & not in C++?

以下程序在 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 编译器。

问题在下一行

char a[5]="Hello";

没有 space 可用于存储终止空值。

默认情况下,gcc 在启用 -fpermissive 选项的情况下不会产生任何错误。因此,它 C.

中编译得很好

根据语言标准的要求,

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

An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

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

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

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

C 和 C++ 中的有效字符串应该有一个 [=11=] 终止符并且在

char a[5]="Hello";

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

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

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

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

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

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

C99 6.7.8/14: An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

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

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

C++11 8.5.2/2: There shall not be more initializers than there are array elements.

因此,对于该语言,编译器应该给出错误。

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

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