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

Lun*_*din 5 c gcc initializer-list

我正在使用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'};
}
Run Code Online (Sandbox Code Playgroud)

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

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

int main (void)
{
  char b[5] = "hello";
}
Run Code Online (Sandbox Code Playgroud)

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

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

oua*_*uah 12

而:

 char a[5] = {'h','e','l','l','o','\0'};
Run Code Online (Sandbox Code Playgroud)

是无效的.

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

这个:

char b[5] = "hello";
Run Code Online (Sandbox Code Playgroud)

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

(C11,6.7.9p14)"字符类型的数组,可以用字符串初始化字面或UTF-8字符串文字,任选在大括号.字符串常量(的连续字节,包括终止空字符,如果有房间或如果数组的大小未知)初始化数组的元素."

 char b[5] = "hello!";
Run Code Online (Sandbox Code Playgroud)

是无效的.

  • @Lundin当初始化程序是字符串文字时,我不会将其视为错误,而应作为特殊规定。 (2认同)

Ste*_*mit 5

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

我同意令人惊讶的是,{'h','e','l','l','o','\0'}初始化器发出警告,而"hello"没有.但这些是两种截然不同的形式,事实证明它们的规则是不同的.当您为阵列提供大小并使用{}表单时,所有初始化程序都必须有空间.但是当你给出一个大小并使用""表格时,对于那种情况和那种情况有一个特殊的例外.

(对于任何一种形式,它在C++中也不合法.)