有没有办法在行为不当的指定初始化器时得到警告?

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

C99 引入了结构指定初始化器的概念。例如,给定:

typedef struct {
    int c;
    char a;
    float b;
} X;

我可以像这样初始化:X foo = {.a = '', .b = 2.0F, .c = 4}; 调用:printf("c = %d\na = %hhu\nb = %f", foo.c, foo.a, foo.b); 会输出:

c = 4
a = 1
b = 2.000000

As mentioned here 这有 "surprising behavior" 分配给 c 然后 a 然后 b,独立于我指定的初始化器的顺序。

如果我有这样的功能,这将成为一个真正的问题:

int i = 0;

int f() {
    return ++i;
}

int g() {
    i += 2;
    return i;
}

int h() {
    i += 4;
    return i;
}

我想这样初始化:X foo = {.a = (char)f(), .b = g(), .c = h()}; 现在当我这样做时:printf("c = %d\na = %hhu\nb = %f", foo.c, foo.a, foo.b); 我得到:

c = 4
a = 5
b = 7.000000

问题是没有警告我的初始化顺序未被遵守。是否有警告或我可以为此启用的东西?

[Live Example]

您可以在 C 中做的最好的(阅读:合理的)事情是在初始化结构之前声明三个临时 const 变量。他们的声明顺序是他们的初始化器的评估顺序。

像这样:

const char a = f();
const float b = g();
const int c = h();

X foo = {.a = a, .b = b, .c = c};

在这种情况下,函数调用的顺序和程序员的意图很明确。

...没有警告我的初始化顺序未被遵守

特定的 初始化顺序 是基于标准中规定的其他内容的期望。 (正如评论中指出的那样)

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]

因此除了未定义(或未指定)行为外,这里没有问题。与其他 C 行为非常相似,例如函数参数求值顺序的歧义。

编辑
C99 对此有话要说:

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

您更喜欢警告(您说得很好,+1)是另一回事。我不确定在 C/C++ 语言中为 -every- -undefined- -behavior- 提供警告是否实用。

值得注意的是,assumptions/opinions in this discussion 为什么 C++ 标准不包括指定初始化器。 (还)...

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