как привести массив uint8 t из 4 в uint32 t в c



Я пытаюсь привести массив uint8_t к массиву uint32_t, но это, кажется, не работает.

Может ли кто-нибудь помочь мне в этом? Мне нужно получить значения uint8_t в uint32_t.

Я могу сделать это с помощью сдвига, но я думаю, что есть простой способ.



uint32_t *v4full;
v4full=( uint32_t *)v4;
while (*v4full) {
if (*v4full & 1)
printf("1");
else
printf("0");

*v4full >>= 1;
}
printf("n");
960   4  

4 ответов:

Учитывая необходимость получить значения uint8_t для uint32_t и спецификации на in4_pton()...

Попробуйте сделать это с возможной поправкой на порядок байтов:

uin32_t i32 = v4[0] | (v4[1] << 8) | (v4[2] << 16) | (v4[3] << 24);

Если v4full является указателем, то строка

uint32_t *v4full;
v4full=( uint32_t)&v4;

Должен выдать ошибку или, по крайней мере, предупреждение компилятора. Может быть, вы хотите сделать

uint32_t *v4full;
v4full=( uint32_t *) v4;

, где я предполагаю, что v4 сам является указателем на массив uint8. Я понимаю, что экстраполирую из неполной информации ...

EDIT поскольку выше, по-видимому, была исправлена опечатка, давайте попробуем еще раз.

Следующий фрагмент кода работает так, как ожидалось - и как я думаю, вы хотите, чтобы ваш код работал. Пожалуйста, прокомментируйте это - почему этот код не делает того, что вы хотите?

#include <stdio.h>
#include <inttypes.h>

int main(void) {
    uint8_t v4[4] = {1,2,3,4};
    uint32_t *allOfIt;
    allOfIt = (uint32_t*)v4;
    printf("the number is %08x\n", *allOfIt);
}

Вывод:

the number is 04030201

Примечание-порядок байтов в напечатанном номере обратный - вы получаете 04030201 вместо 01020304, Как вы могли бы ожидать / хотели. Это связано с тем, что моя машина (архитектура x86) является малоэндианской. Если вы хотите убедиться, что порядок байтов соответствует вашему желанию (другими словами, что элемент [0] соответствует наиболее значимому байту), вам лучше использовать решение @bvj - смещение каждого из четыре байта в правильном положении в вашем 32-битном целочисленном.

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

Есть проблема с вашим примером-фактически с тем, что вы пытаетесь сделать (поскольку вы не хотите сдвигов).

Видите ли, это малоизвестный факт, но Вам не разрешается переключать типы указателей таким образом

В частности, такой код является незаконным:

type1 *vec1=...;
type2 *vec2=(type2*)vec1;
// do stuff with *vec2
Единственный случай, когда это законно, - это если type2 является char (или unsigned char или const char и т. д.), но если type2 является любым другим типом (uint32_t в вашем примере), это противоречит стандарту и может ввести ошибки в коде при компиляции с оптимизацией -O2 или -O3. Это называется "правилом строгого сглаживания" и позволяет компиляторам предполагать, что указатели различных типов никогда не указывают на связанные точки в памяти - так что при изменении памяти одного указателя компилятору не нужно перезагружать все остальные указатели. Компиляторам трудно найти случаи нарушения этого правила, если только вы не сделаете это болезненно ясным для него. Например, если изменить код на сделайте это:
uint32_t v4full=*((uint32_t*)v4);

И скомпилировать с помощью -O3 -Wall (я использую gcc) вы получите предупреждение:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
Таким образом, вы не можете избежать использования сдвигов.

Примечание: он будет работать на более низких настройках оптимизации, а также будет работать в более высоких настройках, если вы никогда не меняете указатель info на v4 и v4_full. Это будет работать, но это все еще ошибка и все еще "против правил".

Еще одно решение:

u32 ip;

if (!in4_pton(str, -1, (u8 *)&ip, -1, NULL))
      return -EINVAL;

... use ip as it defined above - (as variable of type u32)

Здесь мы используем результат функции in4_pton (ip) без каких-либо дополнительных переменных и отливок.

Comments

    Ничего не найдено.