2016-03-30 4 views
6

Скажем, у меня есть этот тип:Безопасно ли ссылаться на структуру, которая инициализируется в ее инициализаторе?

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

Почему заказ важен? – chux

+0

BTW, должен убедиться, что продукт рассчитан с использованием 'size_t' math:' bmp.w * bmp.h' -> '(size_t) bmp.w * bmp.h'. – chux

+0

Если сначала инициализируется поле 'bmp.b', то поля' bmp.w' и 'bmp.h' содержат мусор во время инициализации' bmp.b' и, следовательно, такие вещи, как 'calloc (-542 * 3546, sizeof (* bmp.b)) '. –

ответ

8

Использование

Bitmap bmp = {w, h, calloc(bmp.w * bmp.h, sizeof(*bmp.b))}; 

не определено поведение. В стандарте C99 есть два элемента, которые обращаются к этому.

6.7.8. Инициализация

...

19 Инициализация должна происходить в списке инициализатора порядке, каждый из инициализатора, предусмотренного для конкретного подобъекта отвергая любой ранее перечисленный инициализатор для того же подобъект.

...

23 Порядок, в котором какие-либо побочные эффекты возникают из выражений списка инициализации unspecified.133)

и сноска 133 говорит:

В частности, порядок оценки не должен совпадать с порядком инициализации субобъекта

Вместе они означают, что bmp.w будет инициализирован до bmp.h. Однако возможно, что calloc(bmp.w * bmp.h, sizeof(*bmp.b)) оценивается до bmp.w и bmp.h. Отсюда неопределенное поведение.

2

Нет, это небезопасно.

Цитируется N1570 6.7.9 Initialization, курсив:

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)}; 
+0

bmp не определен в первой строке, поэтому он должен быть '* b = calloc (w * h, sizeof (* b));' – RomCoo

+0

@RomCoo Спасибо, что указали, что –

Смежные вопросы