Reputation: 313
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
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
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
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
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
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
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
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