引用在其初始化程序中初始化的结构是否安全?

时间:2016-03-30 15:57:47

标签: c struct initialization

说我有这种类型:

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.wbmp.h字段已初始化?

2 个答案:

答案 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)};