说我有这种类型:
struct Bitmap
{
int w, h, *b;
};
我正在初始化它:
int w = 7, h = 4;
struct Bitmap bmp = {w, h, calloc(bmp.w * bmp.h, sizeof(*bmp.b))};
是否可以保证编译器会按顺序初始化struct
?我是否可以确定在bmp.b
字段初始化时,bmp.w
和bmp.h
字段已初始化?
答案 0 :(得分:8)
使用
Bitmap bmp = {w, h, calloc(bmp.w * bmp.h, sizeof(*bmp.b))};
是未定义的行为。 C99标准中有两个项目可以解决这个问题。
<强> 6.7.8。初始化强>
...
19初始化应在初始化器列表顺序中进行,每个初始化器为特定子对象提供,覆盖同一子对象的任何先前列出的初始化器。
...
23初始化列表表达式中出现任何副作用的顺序未指定.133)
和脚注133说:
特别是,评估顺序不必与子对象初始化的顺序相同
他们的意思是bmp.w
将在bmp.h
之前初始化。但是,有可能在calloc(bmp.w * bmp.h, sizeof(*bmp.b))
和bmp.w
初始化之前评估bmp.h
。因此未定义的行为。
答案 1 :(得分:2)
不,这不安全。
引自N1570 6.7.9初始化,强调我的:
23初始化列表表达式的评估是 相对于彼此不确定地排序,因此 发生任何副作用的顺序未明确。
在您的代码中,calloc(bmp.w * bmp.h, sizeof(*bmp.b))
和bmp.w
初始化之前,不保证会对bmp.h
进行评估。这意味着你必须写
int w = 7, h = 4, *b = calloc(w * h, sizeof *b);
struct Bitmap bmp = {w, h, b};
或
struct Bitmap bmp = {w, h, calloc(w * h, sizeof *b)};