Здравствуйте. Интересует такой вопрос. Я определяю структуру: Код (Text): struct color_t { uint8_t r; uint8_t g; uint8_t b; uint8_t a; }; Теперь хочу скопировать структуру в битмап, типа так: Код (Text): uint32_t pixel; color_t color; // ... pixel = *(uint32_t*)(&color); Проблема в том, что я изначально не знаю какое выравнивание полей сделает компилятор. Вообще, это зависит как от конкретного компилятора, так и от его настроек. В VC есть __declspec(align(8)), но не хотелось бы привязываться к конкретному синтаксису. Единственное, что приходит в голову: Код (Text): struct color_t { uint32_t r : 8; uint32_t g : 8; uint32_t b : 8; uint32_t a : 8; };
Правила выравнивания у всех одинаковые - смещение поля кратно наименьшему из двух значений: либо размеру самого поля, либо значению align. Т.е. align служит не для увеличения кратности выравнивания, а наоборот для ее ограничения. Поэтому в структуре, состоящей только из одних однобайтовых полей, все эти поля будут "выравнены" на 1 независимо от align, и только общий размер структуры м.б. увеличен, если он окажется не кратен 4-м
> Поэтому в структуре, состоящей только из одних однобайтовых полей, все эти поля будут "выравнены" на 1 независимо от align, и только общий размер структуры м.б. увеличен, если он окажется не кратен 4-м пруфлинк нужен желательно на стандарт.
Конечно нет. Это "негласное" правило для x86, вытекающее из рекомендаций Intel\AMD выравнивать данные на "натуральный размер операнда"
n0name, вот и я о том-же. Я хочу разобраться как сделать рабочий код по стандарту. Домыслы, рекомендации, костыли мне не нужны - и так не трудно догадаться как сделать рабочий вариант.
cupuyc Тогда либо сразу делай "не эффективно", либо положись еще на один домысел\костыль - надежду на оптимизирующие возможности компилятора или процессора: Код (Text): if (sizeof(color_t) == sizeof(uint32_t)) { pixel = *(uint32_t*)(&color); } else ... Если размеры совпадают, то либо оптимизирующий компилятор выбросит из кода и проверку размера и ветку else, ну либо процессор с предсказанием ветвлений ошибется макс. 1 раз и затем будет ходить только по "эффективной" ветке
leo, ещё раз повторю. Вопрос не стоит как вставить костыль. Вопрос стоит как сделать по стандарту. До подобных костылей я и сам могу догадаться. Сейчас гляну что даёт оптимизация. Будет ли она конструкцию, типа заменять на обычное присвоение...
Стандарт. Но что касается отдельных полей в pod структуре, то тут стандарт ничего не говорит. В общем гарантий того, что данные будут лежать плотно, безусловно нет.
cupuyc Что в приведенном коде #9 не соответствует стандарту ?! Зачем ?! На всех возможных компиляторах под все процессоры глянешь ?!
> Но что касается отдельных полей в pod структуре, то тут стандарт ничего не говорит. почему же, кое-что есть: Этот фрагмент как раз и говорит нам о том, что выравнивание в структуре зависит от реализации компилятора.
cupuyc Вот чудак-человек, в чем ты видишь костыль, если согласно тому же стандарту размер структуры зависит от реализации компилятора и следовательно ты его не можешь знать заранее и поэтому "якобы" проверяешь в рантайме ? Копировать 4 байта из структуры в uint32 стандарт тоже не запрещает - значит все законно и в рамках стандарта. Ну а конкретный компилятор под конкретную платформу уже сам решит как оптимизировать этот код
Код (Text): struct { union { uint32_t bbb; struct { uint8_t a; uint8_t r; uint8_t g; uint8_t b; } ddd; } } st; .... st.ddd.a = 0xff; st.ddd.r = red; st.ddd.g = green; st.ddd.b = blue; pixel = &(st.bbb); Для всех машин с одинаковой endianess будет работать одинаково. Для остальных - поменять порядок переменных в ddd.