For a structure variable,why is the initializer {21,19,3.6} same as {{21,19},3.6},but not vice-versa?

限于喜欢 提交于 2020-01-04 01:20:32

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!