voltaa7
voltaa7

Reputation: 313

Array initialisation in C

I have doubt regarding the following piece of code :

int main()
{
    int array1 = {1,2,3,4,5}; //error in c++ , warning in c
    int array2[] = {1,2,3,4,5};
    int array3[5] = {1,2,3,4,5};
}

This piece of code gives a error on line 3 in c++ but not in c?

I know array1 is actually an int and array2 and array3 are arrays, so why doesn't a c compiler show a error , but just a warning: "excess elements in scalar initialization"

Is there a use of such a definition and why is it valid in c?

Upvotes: 20

Views: 2134

Answers (7)

Baldrickk
Baldrickk

Reputation: 4409

It isn't valid in C. It just has less checks on the code. This is Undefined behaviour.

From: C11 draft N1570; 6.7.9 Initialisation

Constraints
2 No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
3 The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.

Definitely breaks constraint 2. Is an int a complete object type?

from Annex J.2 (undefined behaviour):

The initializer for a scalar is neither a single expression nor a single expression enclosed in braces (6.7.9).

extra:
@James Kanze:

prog.c:4:12: error: expected identifier or ‘(’ before numeric constant
  int i = 1,2,3,4,5;
            ^

you can do it, but you need to make it one expression:

int i = (1,2,3,4,5); //need parenthesis, evaluates to 5, values 1-4 thrown away.

Compiling with an int initialised with an initalizer-list spawns a warning (in gcc):

prog.c:5:2: warning: excess elements in scalar initializer [enabled by default]
  int j = {1,2,3,4,5};
  ^

but it appears that the compiler is smart enough to only initialise the int and not the following memory. demo

Upvotes: 15

Serge Ballesta
Serge Ballesta

Reputation: 149175

C is a low-level permissive language. It allows to affect a pointer to an int.

int array1 = {1,2,3,4,5};

EDIT :

I should have tested it under different compilers before writing stupid things.

This is rejected as error by MSVC (2008).

Both gcc and clang issue a warning excess elements in scalar initializer and simply affect 1 to a.

Upvotes: 1

Jens Gustedt
Jens Gustedt

Reputation: 78973

As your compiler says, this is not correct for C, either. The important thing to notice here is that in case of such "constraint violations" (the official term) the compiler may just produce a diagnostic (which your compiler did) and continue.

That is why generally you should ensure that your code compiles without any diagnostic whatsoever.

Upvotes: 2

James Kanze
James Kanze

Reputation: 154047

Like everyone else, I assume that the line you're wondering about is:

int array1 = {1,2,3,4,5};

In this case, there is no difference between C and C++; the line is arguably legal in both languages, but it doesn't mean what you might think. In both C and C++, there is a statement to the effect that if the type is a scalar type (int is), then the contents of the {...} must be a single expression. And 1,2,3,4,5 can be interpreted as a single expression (with the comma operator); something like:

int array1 = 1, 2, 3, 4, 5;

is clearly legal.

It's somewhat ambiguous, however, since in both languages, the grammar for this type of initialization makes the , punctuation, and not an operator. So it is a question of interpretation; is the statement that the contents must be a single expression a constraint on the grammar (which would cause the comma to become an operator), or a constraint on the results of evaluating the specified grammar. My intuitive feeling is that the second is the intent, and that the statement should result in an error. But the difference isn't between C and C++, but between the way the authors of the compilers are interpreting the standard.

EDIT:

On rereading a little closer: in the C++ standard, it explicitly says that

If T is a scalar type, then a declaration of the form

    T x = { a };

is equivalent to

    T x = a;

Which doesn't leave much wriggle room: in C++, the statement seems clearly legal; it's only in C where there is some ambiguity.

Upvotes: 3

Lundin
Lundin

Reputation: 215115

It is not valid C. See C11 6.7.9:

No initializer shall attempt to provide a value for an object not contained within the entity being initialized.

I would guess that you are using gcc. Then if you want your program to behave as strict standard C, compile it as such:

gcc -std=c11 -pedantic-errors

gives

error: excess elements in scalar initializer

Upvotes: 25

Some programmer dude
Some programmer dude

Reputation: 409472

It's valid as per the C specification.

Quote from C11 section 6.7.9 (Initialization):

Syntax

1 initializer:
    assignment-expression
    { initializer-list }
    { initializer-list , }

So an initializer can either be a direct expression (assignment-expression above), or a brace-enclose list of initializers. The constraints in that section of the standard does not limit this for "normal" (non-array or non-pointer) variables.

That allows you to write e.g.

int a = { 1 };

Upvotes: 11

celeborn
celeborn

Reputation: 292

The right way to initialize an array in C/C++ is:

int array2[] = {1,2,3,4,5};

Here the square brackets actually inform the compiler that this is an array, a set of numbers in your case. In that way of initialization it is not necessary to specify the length of the array. The compiler will know.

The second way is to define an array and post initialize it:

int array3[5];
int *array = new int[5];

In this case you'll need to inform the compiler what size the array will be. Moreover, in the second case you need to delete the memory manually.

Upvotes: 2

Related Questions