我使用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";
}
我认为这两种形式是100%相同的。 C标准中是否有任何理由或微妙之处,为什么后者不应该发出警告?
或者这是编译器错误?我知道C标准允许多余的初始化器,与C ++不同,所以我不相信gcc是必需的来进行诊断。但我希望编译器能够始终如一地发出警告。
答案 0 :(得分:11)
虽然:
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!";
无效。
答案 1 :(得分:5)
这是C标准中一个奇怪的怪癖。回到当天,人们偶尔会使用固定长度的非空终止字符串。 (一个例子是V7 Unix中的14个字符的文件名。)因此,为了让这些旧程序继续编译,使用字符串常量初始化显式大小的char
数组是合法的正如您刚刚观察到的那样刮掉'\0'
。
我同意令人惊讶的是{'h','e','l','l','o','\0'}
初始化程序警告,"hello"
初始化程序没有。但这些是两种截然不同的形式,事实证明它们的规则是不同的。当您为数组提供大小并使用{}
表单时,所有初始值设定项都必须有空间。但是当你给出一个大小并使用""
表格时,那个案例就是一个特例,只有那种情况。
(对于任何一种形式,它在C ++中也不合法。)
答案 2 :(得分:2)
在
char b[5] = "hello";
\0
未附加到字符串,因为数组b
的大小为5
。这是有效的。编译器将其视为
char b[5] = {'h','e','l','l','o'};
此处b
是char
的数组。但是,它不能用于假定字符串文字的地方。例如,您不能在b
中使用printf
%s
说明符或str
家庭功能使用<cfimage action="convert" overwrite="no" destination='image.png' source='image.eps'/>
。