Структурное однобайтовое выравнивание противоречит требованию выравнивания архитектуры?

Я ранее отправил вопрос Вот о выровненном доступе во время приведения указателя. Таким образом, лучше не использовать невыровненный доступ, чтобы быть полностью переносимым, потому что некоторая архитектура может выдать исключение, или производительность может быть значительно ниже по сравнению с выровненным доступом.

Тем не мение, есть случаи что я хочу использовать однобайтовое выравнивание, например, во время передачи сетевых данных, я не хочу добавлять дополнительное заполнение внутри структуры. Обычно здесь делается следующее:

#pragma pack (push, 1)
struct tTelegram
{
u8 cmd;
u8 index;
u16 addr1_16;
u16 addr2_16;
u8  length_low;
u8 data[1];
};
#pragma pack (pop)

Тогда вы, возможно, уже знаете мой вопрос: если я применяю однобайтовое выравнивание в моей структуре, значит ли это, что она не может быть полностью переносимой, потому что члены структуры не выровнены? Что делать, если я хочу, чтобы не было отступов и переносимости?

3

Решение

Во-первых, неправильный доступ к памяти относится к отдельным частям данных, которые охватывают несколько слов в памяти. Например: в 32-битной системе 32-битная int по адресу 0, 4, 8 и т. д. выровнены, но по 1, 2, 3, 5, 6, 7, 9 и т. д. будут смещены.

Во-вторых, неправильно выровненные данные не «выдают исключение» в смысле C ++, но могут вызвать прерывание / прерывание / исключение на уровне ЦП — например, SIGBUS в UNIX, где вы обычно устанавливаете обработчик сигнала, чтобы реагировать на это, но если вам нужно было бы анализировать выровненные данные переносимым способом, вы бы этого не делали, перехватывая сигналы — вы бы вручную закодировали шаги для упаковки и распаковать данные, охватывающие границы слов.

В вашем tTelegram На самом деле, данные не «выровнены», но процесс сдвига битов и маскирования данных при их упаковке / распаковке из регистра все еще, вероятно, медленнее — требует больше инструкций машинного кода — чем использование данных, которые занимают независимое слово.

Что касается переносимости — все неигровые компиляторы будут иметь возможность упаковать так, как вы описали, но точная прагма будет отличаться, расположение байтов в многобайтовых значениях может все еще быть с прямым порядком байтов или с прямым порядком байтов (или что-то странное), и в то время как некоторые процессоры разрешают доступ к данным со смещением (например, x86), другие не позволяют (например, Ultrasparc).

3

Другие решения

При передаче данных между разными компьютерами вы всегда хотите отформатировать данные. Обратите внимание, что формат данных не обязательно должен быть читаемым, но он вполне может быть двоичным. Бинарный формат будет включать в себя точную позицию каждого элемента данных, его тип, для многобайтовых данных — порядок появления байтов, размер или способ определения размера и т. Д. Если не использовать определенный формат, будет кусаться, вероятно, раньше, чем потом.

Другими словами, хотя я видел подходы, которые вы описываете, использованные, я не думаю, что они нормальные и, конечно, они ненормальные, когда речь идет об определенном формате между различными организациями (компаниями, наверняка, вероятно, также между различными отделами и / или группами). ). В местах, где я работал для получения и отправки данных, был точно определен точный формат. Если определенный формат может быть сопоставлен с макетом данных в struct он, конечно, также используется для декодирования данных, но известно, что он не является переносимым, а код, предназначенный для переноса, не пытается использовать подобные средства. Вместо этого он использует что-то, что читает / записывает соответствующие записи и декодирует / кодирует их соответствующим образом. Часто код декодирования / кодирования генерируется из некоторого мета-формата, описывающего точную структуру данных.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector