是否有办法警告行为不端的指定初始化器?

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

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

我可以初始化为: X foo = {.a = '\1', .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

如此处所述,这具有分配给c然后b然后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

问题是没有警告我的初始化顺序没有得到遵守。 是否有警告或我能为此启用的内容?

[ 实例 ]

…没有警告我的初始化顺序没有得到遵守

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

C99第6.7.9节,第23页:23初始化列表表达式的评估相对于彼此不确定地排序,因此未指定任何副作用发生的顺序。 [强调我的]

因此,除了未定义(或未指定 )的行为之外,没有问题。 与其他C行为非常相似,例如函数参数评估顺序的模糊性。

编辑
C99对此有这样的说法:

来自C99§6.5.2.2p10:
函数参数的评估顺序未指定 ,函数指示符的评估顺序,实际参数和实际参数中的子表达式未指定,但在实际调用之前有一个序列点。
[强调我的]

在这里阅读更多

你更喜欢警告(你说得好,+1)是另一回事。 我不确定在C / C ++语言中为 – every – – undefined行为提供警告是多么实际。

有趣的是, 在本讨论中注意到为什么C ++标准不包括指定初始化器的一些陈述的假设/意见。 (还)……

… C ++更感兴趣的是将灵活性放在类型设计器的一边,因此设计人员可以很容易地正确使用类型并且难以正确使用。

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

像这样的东西:

 const char a = f(); const float b = g(); const int c = h(); X foo = {.a = a, .b = b, .c = c}; 

在这种情况下,函数调用的顺序和程序员的意图是清楚的。