Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this valid C

Tags:

c

I came across this code on reddit. I would have thought that type conversions would have caused this to be invalid.

int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 }; 

On clang, I get a few warnings about excessive elements and braces in a scalar initializer. But the contents of a is [1, 7, 9].

Is this actually legitimate, and if it is, could someone explain what exactly is going on?

like image 545
Bill Lynch Avatar asked Mar 20 '12 17:03

Bill Lynch


People also ask

Which is a valid statement in C?

0 , for example, is a valid expression (it's an octal literal int type with a value zero). And a statement can be an expression followed by a semi-colon. 0; is a legal statement.

Is all C code valid C++ code?

In the strict mathematical sense, C isn't a subset of C++. There are programs that are valid C but not valid C++ and even a few ways of writing code that has a different meaning in C and C++. However, C++ supports every programming technique supported by C95 (C90 plus an Amendment) and earlier.

Which of the following is not valid C variable name?

Which of the following is not a valid variable name declaration? Explanation: Variable name cannot start with a digit.

What does x1 return C++?

x & 1 produces a value that is either 1 or 0 , depending on the least significant bit of x : if the last bit is 1 , the result of x & 1 is 1 ; otherwise, it is 0 . This is a bitwise AND operation. x >>= 1 means "set x to itself shifted by one bit to the right".


2 Answers

The excess elements are just ignored. There are two parts of 6.7.8 Initialization that you care about. First, from paragraph 17:

Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union.

That one explains why you get 1, 7, and 9 - the current object gets set by those braces. Then as to why it doesn't care about the extras, from paragraph 20:

... only enough initializers from the list are taken to account for the elements or members of the subaggregate or the first member of the contained union; any remaining initializers are left to initialize the next element or member of the aggregate of which the current subaggregate or contained union is a part.

like image 69
Carl Norum Avatar answered Oct 10 '22 15:10

Carl Norum


  int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 }; 

is invalid.

It is invalid for the same reasons int b[1] = {1, 2}; is invalid: because C99 says

(C99, 6.7.8p1) "No initializer shall attempt to provide a value for an object not contained within the entity being initialized."

The last element 10 in a initializers attempts to provide a value for an object not contained within the entity being initialized.

like image 37
ouah Avatar answered Oct 10 '22 16:10

ouah