[英]how to cast uint8_t array of 4 to uint32_t in 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");
鉴于需要获取uint32_t的uint8_t值,以及in4_pton()的规格...
尝试使用可能的字节顺序更正:
uint32_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
数组的指针。 我意识到我从不完整的信息中推断......
编辑,因为上面似乎已经解决了一个错字,让我们再试一次。
以下代码片段按预期工作 - 我认为您希望代码能够正常工作。 请评论一下 - 这段代码怎么做不到你想要的?
#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位整数的正确位置。
顺便提一下,如果需要,你可以看到这个早期的答案是非常有效的方法(告诉编译器使用CPU的内置指令)。
您的示例存在问题 - 实际上是您正在尝试做的事情(因为您不希望轮班)。
看,这是一个鲜为人知的事实,但是你不允许以这种方式切换指针类型
具体来说,这样的代码是非法的:
type1 *vec1=...;
type2 *vec2=(type2*)vec1;
// do stuff with *vec2
这是合法的唯一情况是如果type2
是char
(或unsigned char
或const char
等),但是如果type2
是任何其他类型(在你的例子中是uint32_t
)它是违反标准的,如果你编译可能会给你的代码引入bug使用-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
,它也可以在更高的设置中工作。 它会工作,但它仍然是一个错误,仍然“违反规则”。
这是一个解决方案:
/* 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;
}
使该代码不可移植的另一个问题是许多架构要求uint32_t
在四字节边界上对齐,但允许uint8_t
具有任何地址。 在不正确对齐的数组上调用此代码会导致未定义的行为,例如使用SIGBUS
使程序崩溃。 在这些机器上,将任意uint8_t[]
强制转换为uint32_t[]
的唯一方法是memcpy()
内容。 (如果以四字节块的形式执行此操作,编译器应针对您的体系结构优化到未对齐的负载或双负载和移位更高效。)
如果您可以控制源数组的声明,则可以#include <stdalign.h>
然后声明alignas(uint32_t) uint8_t bytes[]
。 经典的解决方案是将字节数组和32位值声明为union
成员和它们之间的type-pun。 使用从malloc()
获得的指针也是安全的,因为这些指针保证适当对齐。
还有一个解决方案
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
)的结果,没有任何额外的变量和铸件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.