#c #bitwise-operators #endianness
#c #побитовые операторы #порядковый номер
Вопрос:
Просматривая SO, я обнаружил, что могу сделать следующее, чтобы извлечь байты из a uint16_t
, а затем собрать их в исходное число:
uint16_t x = 700;
// extract the bytes
uint8_t byte1 = (x >> 8) amp; 0xFF;
uint8_t byte2 = x amp; 0xFF;
// reassemble
uint16_t y = (byte1 << 8) byte2;
Но, насколько я понимаю, это будет работать только в системах с малым порядком, а не в системах с большим порядком.
Есть ли способ добиться того же самого независимо от порядкового номера системы?
Комментарии:
1. Нет, это будет работать в любой системе.
2. Порядковый номер не имеет значения. Биты 0..7 16-битного значения всегда являются наименее значимыми. Порядковый номер определяется последовательностью, в которой он хранится в памяти.
3. @KamilCuk «это будет работать в любой системе» -> Возможно. Когда
bytes1 >= 128
иint
является 16-разрядным,byte1 << 8
это UB . Тем не менее, я никогда не видел 16-разрядную систему, которая не работала бы так, как хотелось.uint16_t y = (1u*byte1 << 8) byte2;
является переносимой альтернативой.
Ответ №1:
Ваш код не зависит от порядкового номера. При просмотре битов переменных с использованием масок они всегда будут выглядеть как порядковые. Байты более высокого порядка будут отображаться слева от байтов младшего порядка. Несмотря на то, что на машинах с малым порядковым номером они меняются местами, мы не стали мудрее.
Однако, с учетом сказанного, вы могли бы вместо этого просто скопировать байты, фактически не глядя на них. Никаких масок, никаких сдвигов, просто скопируйте байты:
// extract the bytes
uint8_t bytes[sizeof(x)];
memcpy(bytes, amp;x, sizeof(x));
// reassemble
uint16_t y;
memcpy(amp;y, bytes, sizeof(y));
Комментарии:
1. Промежуточный результат
bytes[]
_intermediate этого кода зависит от порядкового номера. Надеюсь, это сработает нормально для OP и «… независимо от порядкового номера системы».2. порядковый номер @chux не имеет значения. Он сохранит и восстановит значение правильно независимо от порядкового номера. Если байты не сохранены и не восстановлены или не переданы между системами с разным порядковым номером. Что также верно для исходного кода OP.
Ответ №2:
Порядковый номер определяет способ сохранения числа в памяти. Однако, когда число загружается из памяти в регистр, оно не зависит от порядкового номера. Все операции с входным номером выполняются через регистры, и результат сохраняется обратно в память в соответствии с порядковым номером.
Eg.
Number = 0xAABB
Memory Address Value
Little Endian 0x3000 0xBB
0x3001 0xAA
Big Endian 0x3000 0xAA
0x3001 0xBB
Но при загрузке в 32-разрядный регистр число все равно будет равно 0xAABB, в результате чего uint8_t byte1 и uint8_t byte2 будут иметь одинаковые значения независимо от порядкового номера.