Что этот дефайн возвращает? Что это за запись?
#define QEMU_BUILD_BUG_ON_STRUCT(x) \
struct { \
int:(x) ? -1 : 1; \
}
Я понимаю что в принципе этот код делает, конкрето ARRAY_SIZE. Но вот этот дефайн выше меня сводит сума
Вот весь стек дефайнов
#define QEMU_IS_ARRAY(x) (!__builtin_types_compatible_p(typeof(x), \
typeof(&(x)[0])))
#define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \
QEMU_BUILD_BUG_ON_ZERO(!QEMU_IS_ARRAY(x)))
#define QEMU_BUILD_BUG_ON_STRUCT(x) \
struct { \
int:(x) ? -1 : 1; \
}
#define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \
sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
QEMU_IS_ARRAY возвращает либо 1 либо 0, так ? 1 - значит массив, 0 не массив(В случае если типы не совпадают) QEMU_BUILD_BUG_ON_STRUCT(x) для меня загадка
Ответы (3 шт):
в C if(x) означает: x!=0
x != 0 ? -1 : 1;
QEMU_BUILD_BUG_ON_STRUCT(1) вернёт структуру с переменной int,
{
int: -1; //-1 - если x != 0 и 1 если x == 0
}
Это очень сильное колдунство... (c) какой-то опер
Что это делает
QEMU_BUILD_BUG_ON, согласно имени, должен вызывать ошибку компиляции, если ей передано истинной значение.QEMU_BUILD_BUG_ON_ZERO— аналогично, но также она должна предстовлять собой выражение с нулевым значением, т.е. по факту этоstatic_assert, возвращающий0.QEMU_BUILD_BUG_ON_STRUCT— просто служебный макрос с помощью которого и реализованQEMU_BUILD_BUG_ON_ZERO
Как это работает
QEMU_BUILD_BUG_ON_STRUCT раскрывается в определение анонимной структуры с безымянным битовым полем:
struct {
int:(x) ? -1 : 1;
}
Или если добавить имена:
struct foo {
int bar:(x) ? -1 : 1;
}
Если значение выражения x равно 0, то битовое поле определяется со значением 1 и структура является корректно объявленной.
В противном случае структура оказывается определённой с битовым полем отрицательной длины (-1), что вызывает ошибку.
QEMU_BUILD_BUG_ON_ZERO(x) — это просто выражение с нулевым значением (n-n); если n корректно (x истинно и определение структуры в QEMU_BUILD_BUG_ON_STRUCT не вызывает ошибку компиляции), то это равносильно следующему:
sizeof(struct {int :1;}) - sizeof(struct {int :1;})
В противном случае оно, само собой, просто вызывает ошибку компиляции.
Так изощряться пришлось, чтобы впихнуть проверку времени компиляции прямо в определение ARRAY_SIZE и оно ничего не испортило.
При определении размера массива обычным способом sizeof(x) / sizeof((x)[0]) крайне легко прострелить себе ногу, когда x не является массивом, а является указателем. Соответственно QEMU_BUILD_BUG_ON_STRUCT работает по аналогии со static_assert - если срабатывает условие !QEMU_IS_ARRAY(x), то будет объявлена структура с битовым полем меньше нуля, что вызовет ошибку времени компиляции.
int * not_arr = NULL;
size_t size = QARRAY_SIZE(not_arr); // error