Как преобразовать массив символов в uint16_t, используя указатель типа приведения?
char bytes[2];
bytes[0] = 0; //0x00
bytes[1] = 24; //0x18
uint16_t* ptrU16 = (uint16_t*)bytes; // I expect it points to the memory block: 0x18
cout << *ptrU16 << endl; // I expect 24, but it is 6144
Что не так в моем коде?
2 ответа
У вас есть маленький порядковый номер. 6144
является 0x1800
, Когда ваша машина представляет 16-битное значение 0x0018
в память, это ставит 0x18
первый байт, а 0x00
второй байт, поэтому при интерпретации двухбайтовой последовательности 0x0018
как uint16_t
, это дает вам 6144
(т.е. 0x1800
), и не 24
(т.е. 0x0018
).
Если вы измените на:
bytes[0] = 24;
bytes[1] = 0;
скорее всего, вы увидите ожидаемый результат.
Если вы действительно хотите получить ожидаемый результат, то вам придется либо вычислить его вручную, например:
uint16_t n = (bytes[1] << 8) + bytes[0];
или, в более общем плане:
char bytes[] = {0x18, 0x00};
uint16_t n = 0;
for ( size_t i = 0; i < 2; ++i ) {
n += bytes[i] << 8 * i;
}
std::cout << n << std::endl;
или вы можете использовать такую функцию, как ntohs()
, так как порядок байтов в сети является прямым порядком байтов.
Вы можете посмотреть в ntohs()
функция. ("Преобразование порядка байтов из сети в хост"). Вы подключили свои данные в режиме с прямым порядком байтов, который традиционно является также порядком сетевых байтов. Независимо от того, на каком хосте вы находитесь, функция ntohs() должна возвращать ожидаемое вами значение. Есть зеркальная функция для перехода от хоста к сетевому порядку.
#include <arpa/inet.h>
...
cout << htons(*ptrU16) << endl;
должен работать и быть переносимым между системами. (т.е. должен работать на Power, ARM, X86, Alpha и т. д.).