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.

+3


source to share


3 answers


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.

+9


source


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.)

+3


source


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.

+2


source







All Articles