有没有办法在行为不当的指定初始化器时得到警告?
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
问题是没有警告我的初始化顺序未被遵守。是否有警告或我可以为此启用的东西?
您可以在 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.
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
问题是没有警告我的初始化顺序未被遵守。是否有警告或我可以为此启用的东西?
您可以在 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.