Как мне преобразовать это шестнадцатеричное значение в u32_t в соответствующее значение char / ascii? - PullRequest
0 голосов
/ 25 апреля 2019

Я пытаюсь прочитать данные из стека TCP и использую эти данные для управления внешними интерфейсами и т. Д. Данные находятся в u32_t, поэтому, если я напишу, например, «test» в интерфейс, шестнадцатеричное значение соответствует 0x74657374. Я хочу преобразовать эти данные в соответствующие им символы, чтобы их было проще использовать. Как преобразовать шестнадцатеричные значения в u32_t в его строку символов?

Я попытался напечатать данные напрямую через спецификатор формата% c, но тогда он показывает только первый символ строки.

/* indicate that the packet has been received */
tcp_recved(tpcb, p->len);
// Put actual data in 32 bit unsigned integer.
tempPtr = (u32_t*)p->payload;
// Print length of the actual data.
xil_printf("Received package. Length = %d \r\n", p->len);
// Reverse the data so it corresponds to the data sent.
u32_t reversedTemp = byte_reverse_32(*tempPtr);

// Prints hex value of data
xil_printf("Data: %08x \r\n",reversedTemp);

if (reversedTemp == 0x6C656431) { /* Read "led1" */
    xil_printf("Data Read: led1");
} else if (reversedTemp == 0x74657374) { /* Read "test */
    xil_printf("Data Read: test");
}

Итак, где я использую полное шестнадцатеричное значение в операторе if, я хочу использовать только строковое значение. Поэтому для проверки теста это должно быть == "test" вместо == 0x74657374.

Ответы [ 3 ]

0 голосов
/ 25 апреля 2019

У вас есть ошибка здесь: tempPtr = (u32_t*)p->payload; ... byte_reverse_32(*tempPtr). Это строгое нарушение псевдонимов и, скорее всего, также неправильный доступ. Не делай этого.

Нет необходимости менять местами байты, чтобы компенсировать бесконечность, так как вы все равно намереваетесь преобразовать их в строку (?). Если это так, вы можете сделать это вместо этого (при условии, что сеть имеет прямой порядок байтов, а процессор - младший):

tcp_recved(tpcb, p->len);
char str[4+1] =
{
  [0] = p->payload[3];
  [1] = p->payload[2];
  [2] = p->payload[1];
  [3] = p->payload[0];
  [4] = '\0'
};
0 голосов
/ 25 апреля 2019

Учитывая:

uint32_t num = 0x74657374 ;

Тогда:

char str[5] = {0} ;
str[0] = num >> 24 ;
str[1] = (num >> 16) & 0xff ;
str[2] = (num >> 8) & 0xff ;
str[3] = num & 0xff ;

Обращение в байтах может быть ненужным, вы можете просто отменить распаковку, чтобы получить строку за один шаг, когда первый символв LSB:

char str[5] = {0} ;
str[0] = num & 0xff ;
str[1] = (num >> 8) & 0xff ;
str[2] = (num >> 16) & 0xff ;
str[3] = num >> 24 ;

Для особых случаев:

  • цель с прямым порядком байтов и первый символ в MSB, или
  • aцель с прямым порядком байтов и первый символ в младшем бите,

, затем просто:

char str[5] = {0} ;
memcpy( str, &num, 4 ) ;

Все, что сказано в этом случае, ваше существующее решение более эффективно, чем сравнение строк или памяти,Но опять же, обращение байтов не нужно - просто измените порядок байтов в целом числе и избегайте «магических чисел»:

#define TEST 0x74736574u ;  // "tset" ("test" reversed)

...

uint32_t temp = *((u32_t*)p->payload) ;
if( temp == TEST ) ...

Преобразование строк, возможно, остается полезным, если вы хотите вывести строки для отладки иличеловеческое представление.

0 голосов
/ 25 апреля 2019

Самое простое решение - получить адрес переменной и затем привести ее к char*.

if (memcmp("test", tempPtr), 4) {
    // The input was "test"
}

Вы можете столкнуться с проблемами, связанными с endianness . Этот ответ имеет решение.

...