是否有办法警告行为不端的指定初始化器?
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};
在这种情况下,函数调用的顺序和程序员的意图是清楚的。