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

时间:2016-01-05 14:39:56

标签: c warnings initialization-list designated-initializer

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

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

[Live Example]

2 个答案:

答案 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:
  函数参数的评估顺序是   未指定的,函数指示符的评估顺序,   实际参数和实际参数中的子表达式是   未指定,但在实际通话之前有一个序列点    [强调我的]

read more here

你更喜欢警告(你说得好,+1)是另一回事。我不确定为 - every - undefined 提供警告是多么实际 - {{3 - 用C / C ++语言编写。

有趣的是要注意一些陈述的假设/意见 behavior 为什么C ++标准不包括指定的初始化器。 (还)......

  

... C ++更感兴趣的是将灵活性放在一边   一个类型的设计师,所以设计师可以使它易于使用   正确输入并且难以正确使用。