Search code examples
cwarningsinitialization-listdesignated-initializer

Is there a Way to Get Warned about Misbehaving Designated Initializers?


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?

[Live Example]


Solution

  • ...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]

    read more here

    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.