Inconsistent gcc diagnostics for string initialization
I am using gcc 4.9.1 / Mingw and compile the code with:
gcc test.c -otest.exe -std = c11 -pedantic-errors -Wall -Wextra
This code gives diagnostics:
int main (void)
{
char a[5] = {'h','e','l','l','o','\0'};
}
error: redundant elements in array initializer char a [5]
However, this code gives no warning:
int main (void)
{
char b[5] = "hello";
}
I thought the two shapes were 100% equivalent. Is there any reason or subtlety to the C standard, etc. why the latter shouldn't give a warning?
Or is it a compiler error? I know that the C standard allows redundant initializers, unlike C ++, so formally I don't believe gcc is required for diagnostics. But I would expect the compiler to warn constantly.
source to share
While:
char a[5] = {'h','e','l','l','o','\0'};
wrong.
(C11, 6.7.9p2) "No initializer should attempt to provide a value for an object not contained in an initialized object."
It:
char b[5] = "hello";
explicitly allowed C (emphasis mine):
(C11, 6.7.9p14) "A character type array can be initialized with a string letter literal or a UTF-8 string literal, optionally enclosed in curly braces. Consecutive bytes of the string literal ( including a null-terminated character if present or an array of unknown size) initialize array elements. "
But
char b[5] = "hello!";
wrong.
source to share
This is a strange quirk in the C standard. On the same day, people sometimes used fixed-length strings that had no null termination. (One example is the 14-character filenames in V7 Unix.) To allow older programs to continue compiling, it is legal to initialize an char
explicit-sized array with a string constant that ends up clearing away '\0'
, as you just noticed.
I am amazed that the initializer {'h','e','l','l','o','\0'}
warned and "hello"
not. But these are two different forms, and it turns out that the rules are different for them. When you size your array and use the shape {}
, there should be room for all of your initializers, period. But when you give a dimension and use a shape ""
, there is a special exception for this case and only for this case.
(It is also not legal in C ++ for any form.)
source to share
IN
char b[5] = "hello";
\0
is not appended to the string because the array b
is sized 5
. It's really. The compiler thinks of it like
char b[5] = {'h','e','l','l','o'};
Here b
is an array of char
s. But it cannot be used in a place where a string literal is intended to be used. For example, you cannot use b
in printf
with a family %s
specifier or str
function.
source to share