为什么“字符串数组的初始化字符串太长”在C中编译得很好而不是在C ++中编译?
以下程序使用警告在C中编译好,但在C ++中编译失败。 为什么? 是什么原因?
#include 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 ++是不同的语言,具有不同的规则。
答案很长:在这两种情况下,原因是数组对于字符串文字来说太小了。 文字由五个可见字符组成,末尾有一个零终结符,因此总大小为6。
在C中,您可以使用太长的字符串初始化数组; 额外的字符被简单地忽略:
C99 6.7.8 / 14:字符类型数组可以由字符串文字初始化,可选地用大括号括起来。 字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素。
编译器有用地警告字符串太大,因为它几乎肯定表示错误; 但它不能拒绝代码,除非你告诉它将警告视为错误。
在C ++中,不允许初始化程序大于数组:
C ++ 11 8.5.2 / 2:初始化器不应多于arrays元素。
因此,对于该语言,编译器应该给出错误。
在这两种语言中,当您希望字符数组的大小适合字符串文字初始化时,您可以保留大小,编译器将做正确的事情。
char a[] = "hello"; // size deduced to be 6
问题出在下面
char a[5]="Hello";
没有剩余空间来存储终止空值。
默认情况下,在启用了-fpermissive
选项的情况下, gcc
不会为此情况产生任何错误。 所以,它在C
编译得很好 。
根据语言标准的要求,
- 对于
C99
标准,第6.7.9章第14段,
字符类型数组可以由字符串文字或UTF-8字符串文字初始化,可选地用大括号括起来。 字符串文字的连续字节(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素。
- 对于
C++11
,第8.5.2章,第2段
没有比数组元素更多的初始化器。
因此,代码用gcc
编译(带警告),用g++
产生错误。
C和C ++中的有效字符串应该有一个\0
终止符并且在
char a[5]="Hello";
null终止符没有空格,a不是有效字符串。
因此,这可能不是C中的错误,但在使用内置字符串函数(如strlen()
和family strlen()
,您肯定会遇到问题。
因为“Hello”是6个char
长,而没有-fpermissive
g ++不会用它初始化5个char
数组,但是gcc会。