У меня есть пара вопросов, которые все взаимосвязаны. По сути, в алгоритме, который я реализую, слово w
определяется как четыре байта, поэтому оно может содержаться как целое в uint32_t
.
Однако во время работы алгоритма мне часто требуется доступ к различным частям слова. Теперь я могу сделать это двумя способами:
uint32_t w = 0x11223344;
uint8_t a = (w & 0xff000000) >> 24;
uint8_t b = (w & 0x00ff0000) >> 16;
uint8_t b = (w & 0x0000ff00) >> 8;
uint8_t d = (w & 0x000000ff);
Однако часть меня думает, что это не особенно эффективно. Я подумал, что лучше использовать профсоюзное представление так:
typedef union
{
struct
{
uint8_t d;
uint8_t c;
uint8_t b;
uint8_t a;
};
uint32_t n;
} word32;
Используя этот метод, я могу назначить word32 w = 0x11223344;
, тогда я могу получить доступ к различным
части, которые мне нужны (w.a=11
в порядке байтов).
Однако на этом этапе я сталкиваюсь с проблемами порядка байтов, а именно, в системах с прямым порядком байтов моя структура определена неправильно, поэтому мне нужно изменить порядок слова до того, как оно будет передано.
Это я могу сделать без особых затруднений. Мой вопрос, следовательно, эффективна ли первая часть (различные побитовые и сдвиги) по сравнению с реализацией с использованием объединения? Есть ли разница между ними вообще? Какой путь мне выбрать на современном процессоре x86_64? Проницательность здесь - просто красная сельдь?
Конечно, я мог бы проверить результаты сборки, но мои знания компиляторов не являются блестящими. Я бы подумал, что объединение будет более эффективным, поскольку оно по сути преобразуется в смещения памяти, например так:
mov eax, [r9+8]
Может ли компилятор понять, что происходит в приведенном выше случае сдвига битов?
Если это имеет значение, я использую C99, в частности, мой компилятор - clang (llvm).
Заранее спасибо.