如何在c中将uint8_t数组4转换为uint32_t

时间:2013-11-30 03:27:40

标签: c casting

我正在尝试将一个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");

6 个答案:

答案 0 :(得分:10)

鉴于需要将uint8_t值提供给uint32_t,以及in4_pton()的规格......

尝试使用可能的字节顺序校正:

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

答案 1 :(得分:4)

如果v4full是指针,则行

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

应抛出错误或至少是编译器警告。也许你的意思是

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

我认为v4本身就是指向uint8数组的指针。我意识到我从不完整的信息中推断......

编辑,因为上面似乎已经解决了一个错字,让我们再试一次。

以下代码片段按预期工作 - 我认为您希望代码能够正常工作。请评论一下 - 这段代码怎么做不到你想要的呢?

#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位整数的正确位置。

顺便提一下,如果需要,您可以看到this earlier answer以非常有效的方式执行此操作(告诉编译器使用CPU的内置指令)。

答案 2 :(得分:4)

您的示例存在问题 - 实际上是您正在尝试做的事情(因为您不希望轮班)。

看,这是一个鲜为人知的事实,但是你不能以这种方式切换指针类型

具体来说,这样的代码是非法的:

type1 *vec1=...;
type2 *vec2=(type2*)vec1;
// do stuff with *vec2

这是合法的唯一情况是type2char(或unsigned charconst 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]

所以你无法避免使用轮班。

注意:它会在较低的优化设置下工作,如果您从未将信息指针更改为v4,它也可以在更高的设置中工作v4_full。它会起作用,但它仍然是一个错误,仍然“违反规则”。

答案 3 :(得分:0)

这是一种解决方案:

/* convert character array to integer */
uint32_t buffChar_To_Int(char *array, size_t n){
    int number = 0;
    int mult = 1;

    n = (int)n < 0 ? -n : n;       /* quick absolute value check  */

    /* for each character in array */
    while (n--){
        /* if not digit or '-', check if number > 0, break or continue */
        if((array[n] < '0' || array[n] > '9') && array[n] != '-'){
            if(number)
               break;
            else
               continue;
        }

        if(array[n] == '-'){      /* if '-' if number, negate, break */
            if(number){
               number = -number;
               break;
            }
        }
        else{      /* convert digit to numeric value   */
            number += (array[n] - '0') * mult;
            mult *= 10;
        }
    }
    return number;
}

答案 4 :(得分:0)

另一个导致该代码不可移植的问题是,许多体系结构要求uint32_t在四字节边界上对齐,但允许uint8_t有任何地址。在未正确对齐的数组上调用此代码将导致未定义的行为,例如使用SIGBUS使程序崩溃。在这些计算机上,将任意uint8_t[]强制转换为uint32_t[]的唯一方法是memcpy()的内容。 (如果您以四字节的块为单位执行此操作,则编译器应优化为在您的体系结构上更有效地使用未对齐的负载或两次加载和一个移位)。

如果您可以控制源数组的声明,则可以先#include <stdalign.h>,然后声明alignas(uint32_t) uint8_t bytes[]。经典的解决方案是将字节数组和32位值都声明为union的成员,并在它们之间键入双关。使用从malloc()获得的指针也是安全的,因为可以确保这些指针适当对齐。

答案 5 :(得分:-1)

还有一个解决方案:

>> python test.py
a, b, c

此处我们使用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)的结果,而不使用任何其他变量和演员。