Преобразование байтов в Int/uint в C

У меня есть массив без знака char [248]; заполненный байтами. Как 2F AF FF 00 EB AB CD EF..... Этот массив является моим байтовым потоком, в котором я храню данные из UART (RS232) в качестве буфера.

Теперь я хочу преобразовать байты обратно в мои uint16 и int32.

В С# я использовал класс BitConverter для этого. например:

byte[] Array = { 0A, AB, CD, 25 };
int myint1 = BitConverter.ToInt32(bytes, 0);
int myint2 = BitConverter.ToInt32(bytes, 4);
int myint3 = BitConverter.ToInt32(bytes, 8);
int myint4 = BitConverter.ToInt32(bytes, 12);
//...
enter code here
Console.WriteLine("int: {0}", myint1); //output Data...

Есть ли аналогичная функция в C? (no.net, я использую компилятор KEIL, потому что код работает на микроконтроллере)

С уважением Сэм

Решения: Путь A)

сначала мне пришлось преобразовать или инициализировать массив как uint8_t ARRAY [248]; Затем я использовал этот код с вашей помощью:

 uint32_t* myint1 = (uint32_t *)&RXBUFF[2]; //test
 uint16_t* myint2 = (uint16_t *)&RXBUFF[6]; //test3

Внимание: Значение int "1985" в шестнадцатеричном выражении представлено как 0x07C1 в myint2. байт, который я отправил, был "C1 07", поэтому микроконтроллер меняет порядок байтов

Я также проведу другие методы.

WR Sam:)

Ответ 1

Да, есть. Предположим, что ваши байты:

uint8_t bytes[N] = { /* whatever */ };

Мы знаем, что 16-битное целое число состоит всего из двух 8-битных целых чисел, например, один имеет число 256 или альтернативно сдвигается на 8:

uint16_t sixteen[N/2];

for (i = 0; i < N; i += 2)
    sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8;
             // assuming you have read your bytes little-endian

Аналогично для 32 бит:

uint32_t thirty_two[N/4];

for (i = 0; i < N; i += 4)
    thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8
        | ((uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24;
             // same assumption

Если байты считаются большими, конечно, вы меняете порядок:

bytes[i+1] | (uint16_t)bytes[i] << 8

и

bytes[i+3] | (uint32_t)bytes[i+2] << 8
    | (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24

Обратите внимание, что существует разница между конечным значением в сохраненном целое и конечной версией запущенной архитектуры. Конкретность, указанная в этом ответе, имеет сохраненное целое число, то есть содержимое bytes. Решения не зависят от конечной конечной архитектуры, поскольку endian-ness учитывается при перемещении.

Ответ 2

Нет стандартной функции, чтобы сделать это для вас на C. Вам нужно будет собрать байты обратно в свои 16- и 32-битные целые числа самостоятельно. Будьте осторожны с контентом!

Вот простой пример с маленьким порядком:

extern uint8_t *bytes;
uint32_t myInt1 = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);

Для системы с большим концом это просто противоположный порядок:

uint32_t myInt1 = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];

Возможно, вам удастся избежать:

uint32_t myInt1 = *(uint32_t *)bytes;

Если вы внимательно относитесь к проблемам выравнивания.

Ответ 3

Вы можете напрямую создать указатель uint16_t * из вашего массива.

uint8_t bytes[N] = { /* whatever */ }; //Shamelessly stolen from Shanbaz

uint16_t* viewAsUint16_t = (uint16_t *)&bytes[0];

Теперь вы можете использовать указатель для доступа к элементам.

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

Ответ 4

            char letter = 'A';
            size_t filter = letter;
            filter = (filter <<  8 | filter);
            filter = (filter << 16 | filter);
            filter = (filter << 32 | filter);
            printf("filter: %#I64x \n", filter); 

результат: "фильтр: 0x4141414141414141"

Ответ 5

В случае little-endian, вы не можете просто использовать memcpy?

memcpy((char*)&myint1, aesData.inputData[startindex], length);