C Endian Conversion: бит за битой

У меня есть специальный беззнаковый long (32 бита), и мне нужно по порядку преобразовать его в порядковый номер - мой long представляет несколько вещей, которые все объединены в один двоичный файл.

Как мне это сделать?

4 ответа

Решение

Порядковый номер представляет собой концепцию на уровне слов, в которой байты хранятся либо в старшем значащем байте (старший порядковый номер), либо в младшем значащем байте первым (маленький порядковый номер). Данные, передаваемые по сети, обычно с прямым порядком байтов (так называемый сетевой порядок байтов). Данные, хранящиеся в памяти на машине, могут располагаться в любом порядке, причем порядок байтов не является наиболее распространенным, учитывая преобладание архитектуры Intel x86. Несмотря на то, что большинство компьютерных архитектур имеют порядок байтов, x86 настолько распространен, что вы чаще всего будете видеть в памяти данные с прямым порядком байтов.

В любом случае, смысл всего этого в том, что порядковый номер является очень специфической концепцией, которая применяется только на уровне байтов, а не на уровне битов. Если ntohs(), ntohl(), htons(), а также htonl() не делай то, что хочешь, тогда то, с чем ты имеешь дело, не является порядком байтов.

Если вам нужно поменять отдельные биты вашего неподписанного длинного или сделать что-то еще сложное, пожалуйста, опубликуйте больше информации о том, что именно вам нужно сделать.

Будьте внимательны, чтобы понять значение слова "порядковый номер". Это относится к порядку байтов в данных, а не битов в байте. Вам может понадобиться только использовать функцию типа htonl или ntohl для преобразования вашего d-слова.

Если вы действительно хотите изменить порядок всех битов в типе данных 32b, вы можете написать итерационный алгоритм для маскировки и смещения каждого бита в соответствующую отраженную позицию.

Простая функция преобразования endianess для длинного без знака может выглядеть следующим образом:

typedef union {
  unsigned long u32;
  unsigned char u8 [ 4 ];
} U32_U8;

unsigned long SwapEndian(unsigned long u)
{
   U32_U8 source;
   U32_U8 dest;

   source.u32 = u;
   dest.u8[0] = source.u8[3];
   dest.u8[1] = source.u8[2];
   dest.u8[2] = source.u8[1];
   dest.u8[3] = source.u8[0];

   return dest.u32;
}

Чтобы инвертировать битовый порядок целого числа, вы можете сдвинуть биты в одном направлении и сдвинуть биты к месту назначения в противоположном направлении.

Другие вопросы по тегам