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
As mentioned here这有“令人惊讶的行为”,分配给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
问题在于没有警告我的初始化顺序没有得到遵守。是否有警告或我能为此启用的内容?
答案 0 :(得分:5)
您可以在C中执行的最好(读取:合理)事情是在初始化结构之前声明三个临时const变量。他们的声明顺序是他们的初始化者的评估顺序。
这样的事情:
const char a = f();
const float b = g();
const int c = h();
X foo = {.a = a, .b = b, .c = c};
在这种情况下,函数调用的顺序和程序员的意图是明确的。
答案 1 :(得分:4)
...没有警告我的初始化顺序不受尊重。
特定的初始化顺序是基于标准中所述的其他内容的期望。 (正如评论中所指出的)
C99 6.7.9节,第23页:23初始化列表表达式的评估是相对于彼此的不确定的顺序,因此 发生任何副作用的顺序是未指定。 [强调我的]
除了未定义(或未指定的)行为之外,此处没有问题。与其他C行为非常相似,例如函数参数评估顺序的模糊性。
<强> 修改 强>
C99对此有这样的说法:
来自C99§6.5.2.2p10:
函数参数的评估顺序是 未指定的,函数指示符的评估顺序, 实际参数和实际参数中的子表达式是 未指定,但在实际通话之前有一个序列点 [强调我的]
你更喜欢警告(你说得好,+1)是另一回事。我不确定为 - every - undefined 提供警告是多么实际 - {{3 - 用C / C ++语言编写。
有趣的是要注意一些陈述的假设/意见 behavior 为什么C ++标准不包括指定的初始化器。 (还)......
... C ++更感兴趣的是将灵活性放在一边 一个类型的设计师,所以设计师可以使它易于使用 正确输入并且难以正确使用。