I came across to this example
struct sct
{
int t[2];
};
struct str
{
sct t[2];
};
int main()
{
str t[2] = { {0, 2, 4, 6}, {1, 3, 5, 7} }; //Who does this work?
cout << t[1].t[0].t[1] << t[0].t[1].t[0];
return 0;
}
This compiles and runs fine. It gives the output 34
I expected the syntax for initialization would be:
str t[2] = { { {0, 2},{4, 6} }, { {1, 3},{5, 7} } };
Instead of
{ {0, 2, 4, 6}, {1, 3, 5, 7} };
But this gave:
In function 'int main()':
error: too many initializers for 'str'
Can someone explain why?
This is a picture to illustrate the way I see this:
There are two ways to specify initializers for arrays: With C89-style initializers, array elements must be initialized in subscript order. Using designated initializers, which allow you to specify the values of the subscript elements to be initialized, array elements can be initialized in any order.
The correct answer is: num[4] = {1,2,3,4}; Concept: The array is a data structure used to store elements in linear order. The array is declared to store elements of a particular data type.
Array initialization is the process of assigning/storing elements to an array. The initialization can be done in a single statement or one by one. Note that the first element in an array is stored at index 0, while the last element is stored at index n-1, where n is the total number of elements in the array.
If the array is not initialized at the time of declaration or any time after that then it will contain some random values in each memory position.
This looks like a simple typo but the situation is complex enough to tackle it step by step.
First let me show the solution that seems to work:
int main()
{
str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
cout << t[1].t[0].t[1] << t[0].t[1].t[0] << endl;
return 0;
}
So we have an array of str
that holds an array of sct
.
Let's start with the latter. You initialize an array of sct
with something like this:
sct x[2] = { {0, 1}, {2, 3} };
Now for a single instance of str
you could go with
str y = { { {0, 2}, {4, 6} } };
What remains for str t[2]
is to arrange two copies of str
initializing expressions inside curly brackets:
str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
Edited: On the first reading I misunderstood the question. After the post was updated it became clear that the question is on why it is possible to shed two pair of braces but shedding just one pair results in a syntax error.
To understand how the parser is interpreting the code you might like to look at the parse tree. You can make gcc dump trees at several stages of the parser with -fdump-tree-...
options. Here -fdump-tree-original
may be useful.
To avoid additional confusion let's make sure the elements of the structures have different names:
struct sct
{
int a[2];
};
struct str
{
sct b[2];
};
Here is the output I got with GCC 7.5 from
>>>> CODE:
str t[2] = { { 0, 2, 4, 6 }, { 1, 3, 5, 7 } };
>>>> tree enabled by -tree-original
struct str t[2] = {{.b={{.a={0, 2}}, {.a={4, 6}}}}, {.b={{.a={1, 3}}, {.a={5, 7}}}}};
You can see that the compiler adds implicit brackets around the initializing expressions for each structure and around the initializing expressions for each named field.
Now consider the expression that fails to compile:
str t[2] = { { {0, 2},{4, 6} }, { {1, 3},{5, 7} } };
A the upper level the tree for this expression would be
/*Step 1: */ struct str t[2] = { {.b={0, 2}, {4, 6} }, {.b={1, 3}, {5, 7} } };
But as b is an array of sct
, we try to initialize that with {0,2}
getting
sct b[2] = {0, 2};
This expands to
struct sct b[2] = {{.a={0, 2} }};
This is valid C++ since the first element of the array is initialized explicitly and the second element is initialized implicitly with zeros.
With this knowledge we get the following tree
/*Step 2: */ struct str t[2] = { {.b={{.a={0, 2} }}, {4, 6} }, {.b={{.a={1, 3} }}, {5, 7} } };
Now we are left with the following:
struct str z = { { { {0,2} }, { {0,0} } }, {4, 6} };
And the compiler rightfully complains:
error: too many initializers for ‘str’
As a final check consider the following declaration
struct sxc
{
sct b[2];
int c[2];
}
struct sxc z = { {0,2} , {4, 6} };
This compiles and result in the following structure:
{ .b = { { .a={0,2} }, { .a={0,0} } }, .c={4, 6} }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With