C99 introduced the concept of designated intializers for structs. So for example, given:
typedef struct {
int c;
char a;
float b;
} X;
I could initialize like: X foo = {.a = '\1', .b = 2.0F, .c = 4};
and calling: printf("c = %d\na = %hhu\nb = %f", foo.c, foo.a, foo.b);
would output:
c = 4
a = 1
b = 2.000000
As mentioned here this has the "surprising behavior" of assigning to c
then a
then b
, independent of the order of my designated initializers.
This becomes a real issue if I have functions like this:
int i = 0;
int f() {
return ++i;
}
int g() {
i += 2;
return i;
}
int h() {
i += 4;
return i;
}
And I want to initialize like this: X foo = {.a = (char)f(), .b = g(), .c = h()};
Now when I do: printf("c = %d\na = %hhu\nb = %f", foo.c, foo.a, foo.b);
I get:
c = 4
a = 5
b = 7.000000
The problem being there was no warning that my initialization order was not respected. Is there a warning or something I can enable for this?
...no warning that my initialization order was not respected.
A particular initialization order is an expectation based on something other then that stated in the standard. (as pointed out in the comments )
C99 section 6.7.9, p23: 23 The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified. [emphasis mine]
There is therefore no problem here except undefined (or unspecified) behavior. Very similar to other C behaviors such as the ambiguity with order of evaluation of function arguments.
EDIT
C99 has this to say about that:
from C99 §6.5.2.2p10:
Order of evaluation of function arguments is unspecified, The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
[emphasis mine]
That you would prefer a warning (which you stated well, +1) is another matter. I am not sure how practical it would be though to provide a warning for -every- -undefined- -behavior- in the C/C++ languages.
It is interesting to note some of the stated assumptions/opinions in this discussion why the C++ standards do not include Designated Initializers. (Yet) ...
...C++ is more interested in putting the flexibility on the side of the designer of a type instead, so designers can make it easy to use a type correctly and difficult to use incorrectly.
The best (read: reasonable) thing you can do in C, is to declare three temporary const variables before you initialize the struct. Their declaration order is the order of evaluation of their initializers.
Something like this:
const char a = f();
const float b = g();
const int c = h();
X foo = {.a = a, .b = b, .c = c};
In this case the order of function calls and the intent of the programmer is clear.
来源:https://stackoverflow.com/questions/34614308/is-there-a-way-to-get-warned-about-misbehaving-designated-initializers