Как преобразовать массив символов в 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(), так как порядок байтов в сети является прямым порядком байтов.

4

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

Вы можете посмотреть в ntohs() функция. («Преобразование порядка байтов сети в хост»). Вы подключили свои данные в режиме с прямым порядком байтов, который традиционно является также порядком байтов в сети. Независимо от того, на каком хосте вы находитесь, функция ntohs () должна возвращать ожидаемое вами значение. Есть зеркальная функция для перехода от хоста к сетевому порядку.

#include <arpa/inet.h>
...
cout << htons(*ptrU16) << endl;

должен работать и быть переносимым между системами. (т.е. должен работать на Power, ARM, X86, Alpha и т. д.).

0

По вопросам рекламы [email protected]