用于字符串初始化的gcc诊断不一致

我正在使用gcc 4.9.1 / Mingw并使用以下代码编译代码:

gcc test.c -otest.exe -std = c11 -pedantic-errors -Wall -Wextra

此代码提供诊断:

int main (void) { char a[5] = {'h','e','l','l','o','\0'}; } 

错误:数组初始化程序中的多余元素char [5]

但是,此代码不会产生警告:

 int main (void) { char b[5] = "hello"; } 

我认为这两种forms是100%相同的。 C标准中有什么理由或微妙之处,为什么后者不应该发出警告?

或者这是编译器错误? 我知道C标准允许多余的初始化器,与C ++不同,所以我不相信gcc 需要进行诊断。 但我希望编译器能够始终如一地发出警告。

而:

  char a[5] = {'h','e','l','l','o','\0'}; 

是无效的。

(C11,6.7.9p2)“没有初始化程序应尝试为未初始化的实体中包含的对象提供值。”

这个:

 char b[5] = "hello"; 

C明确允许(强调我的):

(C11,6.7.9p14)“字符数组的数组可以用字符串文字或UTF-8字符串文字初始化,可选择用大括号括起来。字符串文字的连续字节( 如果有空格或者空格,则包括终止空字符)如果数组的大小未知)初始化数组的元素。“

  char b[5] = "hello!"; 

是无效的。

这是C标准中一个奇怪的怪癖。 在当天,人们偶尔会使用固定长度的非空终止字符串。 (一个例子是V7 Unix中的14个字符的文件名。)因此,为了让这些旧程序继续编译,使用字符串常量初始化显式大小的char数组是合法的,最终会刮掉'\0' ,正如你刚刚观察到的那样。

我同意令人惊讶的是, {'h','e','l','l','o','\0'}初始化器警告,而"hello"初始化器没有。 但这些是两种截然不同的forms,事实certificate它们的规则是不同的。 当您为数组提供大小并使用{}表单时,所有初始值设定项都必须有空间。 但是当你给出一个大小并使用""forms时,对于那种情况和那种情况只有一个特例。

(对于任何一种forms,它在C ++中也是不合法的。)

 char b[5] = "hello"; 

\0未附加到字符串,因为数组b的大小为5 。 这是有效的。 编译器将其视为

 char b[5] = {'h','e','l','l','o'}; 

这里b是一个char数组。 但是,它不能用于假定字符串文字的地方。 例如,您不能在带有%s说明符或str族函数的printf使用b