问题
In the following example,I've illustrated this using two structures test1
and test2
.The first has two elements-an integer array sized two,and a float element.The second structure has 3 elements,2 integers and one float.
I initialize two structure variables s1 and s2 for test1 as:
s1={{23,52},2.5},s2={21,19,3.6};
Both work fine even though for s2 I have taken out the braces that enclose the array elements.It works fine without warning and output is correct.But when I initialize 2 variables for test2 as follows:
v1={{23,52},2.5},v2={21,19,3.6};
I get incorrect output when I try to print out values of v1 and these are the warnings that I had got upon compilation:
warning: braces around scalar initializer|
warning: (near initialization for 'v1.list1')|
warning: excess elements in scalar initializer|
warning: (near initialization for 'v1.list1')|
||=== Build finished: 0 errors, 4 warnings ===|
Based on this premise,please clear the following doubt that arise:
Question: If using v1={{23,52},2.5}
instead of v1={23,52,2.5}
confuses the compiler about whether the first 2 numbers are distinct integer elements of the structure or part of an integer array element of the structure,then why doesn't using s2={21,19,3.6}
instead of s2={{21,19},3.6}
confuse the compiler into thinking that the structure varialbe s2 has 3 elements (2 integer elements and one float),instead of 2 elements (one integer array of size 2 and a float)?What I especially want to understand is why is the first case about v1's initialization wrong.
#include<stdio.h>
struct test1{
int list[2];
float rate;
}s1={{23,52},2.5},s2={21,19,3.6}; //Works fine
struct test2{
int list1;
int list2;
float rate;
}v1={{23,52},2.5},v2={21,19,3.6}; //Messes things up
int main(void)
{
printf("%d,%d,%f\n",s1.list[1],s2.list[1],s2.rate);
printf("%d,%d,%f\n",v1.list1,v1.list2,v1.rate);
}
回答1:
This is just a consequence of how the rules for initialisers are defined. If the current object of the initialisation is a struct
, union
or array, then if the next initialiser begins with a {
then the initialisers enclosed by that brace and its matching }
are used to initialise the members of that object; otherwise, it just marches through the list of initialisers, taking as many as it needs.
So, in the first case s1={{23,52},2.5}
, the current object starts out as s1.list
. This is an array, and the next initialiser is { 23, 52 }
, so that's used to initialise the array. s1.rate
is now the current object, and the next initialiser is 2.5
, so that works as expected.
In the second case s2={21,19,3.6}
, the current object starts out as s2.list
. This is an array, but the next initialiser does not start out with {
- so it takes as many values as it needs (in this case, two), and initialises the array with 21
and 19
. s2.rate
is now the current object, and the next initialiser is 2.5
, so again that works as expected.
In the third case v1={{23,52},2.5}
, the current object starts out as v1.list1
. This is a scalar, and the corresponding initialiser is {23, 52}
. This violates a constraint of the language - "The initializer for a scalar shall be a single expression, optionally enclosed in braces" - so that's why you get a warning. Formally the behaviour of your program is undefined, but it appears that your compiler just uses the first value contained in the initialiser and discards the excess ones. The current object is now v1.list2
, and the next initialiser is 2.5
, so the wrong value is used to initialise this member. There is no initialiser for v1.rate
; since v1
has static storage duration, this member is initialiser to 0.0
.
In the forth case v2={21,19,3.6}
, the current object starts out as v1.list1
, and the next initialiser is 21
- this value is used to initialise the member. After this the current object is v1.list2
and the next initialiser is 19
; then v1.rate
is the current object and the next initialiser is 3.6
.
For minimum confusion, you should always use a brace-enclosed initialiser for each struct
or array subobject.
回答2:
In the case of the variable s2
, the compiler knows the size of the embedded array, so it can properly assign to it even without the bracers. you might however get a warning that suggests you to use bracers, and if you don't then I suggest you enable more compiler warnings (it's good to fix warnings, as they might indicate errors that might be valid C but invalid logic).
In the case v1
, you can't use extra bracers because there is no compound data type (structure/union/array). The bracers {}
can only be used to initialize compound data types.
来源:https://stackoverflow.com/questions/16514806/for-a-structure-variable-why-is-the-initializer-21-19-3-6-same-as-21-19-3-6