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

Inconsistent gcc diagnostic for string initialization

我正在使用 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','[=10=]'};
}

error: excess elements in array initializer char a[5]

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

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

我认为这两种形式是 100% 等价的。 C 标准等中是否有任何理由或微妙之处为什么后者不应发出警告?

或者这是一个编译器错误?我知道 C 标准允许过多的初始值设定项,这与 C++ 不同,所以我正式认为 不需要 gcc 来进行诊断。但我希望编译器能够始终如一地发出警告。

char b[5] = "hello";  

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

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

这里b是一个char的数组。但是,它不能用于应该使用字符串文字的地方。例如,您不能在 printf 中将 b%s 说明符或 str 系列函数一起使用。

同时:

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

无效。

(C11, 6.7.9p2) "No initializer shall attempt to provide a value for an object not contained within the entity being initialized."

这个:

char b[5] = "hello";

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

(C11, 6.7.9p14) "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."

但是

 char b[5] = "hello!";

无效。

这是 C 标准中的一个怪癖。过去,人们偶尔会使用固定长度、非 null 终止的字符串。 (一个例子是 V7 Unix 中的 14 个字符的文件名。)所以为了让那些旧程序继续编译,用一个字符串常量初始化一个明确大小的 char 数组是合法的,该字符串常量最终会刮掉 '[ =11=]',正如您刚刚观察到的那样。

我同意 {'h','e','l','l','o','[=12=]'} 初始值设定项发出警告而 "hello" 初始值设定项没有发出警告,这令人惊讶。但这是两种截然不同的形式,事实证明它们的规则是不同的。当您为数组指定大小并使用 {} 形式时,必须为所有初始化程序留出空间,句号。但是当你给出一个尺寸并使用 "" 形式时,这种情况有一个特殊的例外,而且只有那种情况。

(这两种形式在 C++ 中也不合法。)