C语言 如何在c中将4的uint8_t数组转换为uint32_t

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20296162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:24:43  来源:igfitidea点击:

how to cast uint8_t array of 4 to uint32_t in c

ccasting

提问by user2714949

I am trying to cast an array of uint8_t to an array of uint32_t, but it seems not to be working.
Can any one help me on this. I need to get uint8_t values to uint32_t.
I can do this with shifting but i think there is a easy way.

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

回答by bvj

Given the need to get uint8_t values to uint32_t, and the specs on in4_pton()...

鉴于需要将 uint8_t 值获取到 uint32_t,以及 in4_pton() 的规格...

Try this with a possible correction on the byte order:

尝试对字节顺序进行可能的更正:

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

回答by rabensky

There is a problem with your example - actually with what you are trying to do (since you don't want the shifts).

您的示例存在问题 - 实际上与您尝试做的事情有关(因为您不想要转变)。

See, it is a little known fact, but you're not allowed to switch pointer types in this manner

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

specifically, code like this is illegal:

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

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

The only case where this is legal is if type2is char(or unsigned charor const charetc.), but if type2is any other type (uint32_tin your example) it's against the standard and may introduce bugs to your code if you compile with -O2or -O3optimization.

唯一合法的情况是 if type2is char(or unsigned charor const charetc.),但如果type2是任何其他类型(uint32_t在您的示例中),则违反标准,并且如果您使用-O2or-O3优化进行编译,可能会给您的代码带来错误。

This is called the "strict-aliasing rule" and it allows compilers to assume that pointers of different types never point to related points in memory - so that if you change the memory of one pointer, the compiler doesn't have to reload all other pointers.

这被称为“严格别名规则”,它允许编译器假设不同类型的指针永远不会指向内存中的相关点 - 这样如果您更改一个指针的内存,编译器就不必重新加载所有其他指针指针。

It's hard for compilers to find instances of breaking this rule, unless you make it painfully clear to it. For example, if you change your code to do this:

编译器很难找到违反此规则的实例,除非您非常清楚地说明它。例如,如果您更改代码以执行此操作:

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

and compile using -O3 -Wall(I'm using gcc) you'll get the warning:

并使用-O3 -Wall(我正在使用 gcc)进行编译,您将收到警告:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

So you can't avoid using the shifts.

所以你不能避免使用轮班。

Note:it will workon lower optimization settings, and it will also work in higher settings if you never change the info pointer to by v4and v4_full. It will work, but it's still a bug and still "against the rules".

注:它将工作在较低的优化设置,它也将在更高的设置工作,如果你从来没有的信息指针改为通过v4v4_full。它会工作,但它仍然是一个错误并且仍然“违反规则”。

回答by Floris

If v4full is a pointer then the line

如果 v4full 是一个指针,那么该行

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

Should throw an error or at least a compiler warning. Maybe you mean to do

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

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

Where I assume v4is itself a pointer to a uint8array. I realize I am extrapolating from incomplete information…

我假设v4它本身就是一个指向uint8数组的指针。我意识到我是从不完整的信息中推断出来的……

EDITsince the above appears to have addressed a typo, let's try again.

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

The following snippet of code works as expected - and as I think you want your code to work. Please comment on this - how is this code not doing what you want?

以下代码片段按预期工作 - 并且我认为您希望您的代码工作。请对此发表评论 - 这段代码如何不符合您的要求?

#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);
}

Output:

输出:

the number is 04030201

Note - the order of the bytes in the printed number is reversed - you get 04030201instead of 01020304as you might have expected / wanted. This is because my machine (x86 architecture) is little-endian. If you want to make sure that the order of the bytes is the way you want it (in other words, that element [0] corresponds to the most significant byte) you are better off using @bvj's solution - shifting each of the four bytes into the right position in your 32 bit integer.

注意 - 打印数字中的字节顺序是相反的 - 您得到的04030201不是01020304您可能期望/想要的。这是因为我的机器(x86 架构)是小端的。如果您想确保字节的顺序是您想要的方式(换句话说,该元素 [0] 对应于最重要的字节),您最好使用 @bvj 的解决方案 - 移动四个字节中的每一个到 32 位整数中的正确位置。

Incidentally, you can see this earlier answerfor a very efficient way to do this, if needed (telling the compiler to use a built in instruction of the CPU).

顺便说一句,如果需要(告诉编译器使用 CPU 的内置指令),您可以看到这个较早的答案是一种非常有效的方法。

回答by Davislor

One other issue that makes this code non-portable is that many architectures require a uint32_tto be aligned on a four-byte boundary, but allow uint8_tto have any address. Calling this code on an improperly-aligned array would then cause undefined behavior, such as crashing the program with SIGBUS. On these machines, the only way to cast an arbitrary uint8_t[]to a uint32_t[]is to memcpy()the contents. (If you do this in four-byte chunks, the compiler should optimize to whichever of an unaligned load or two-loads-and-a-shift is more efficient on your architecture.)

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

If you have control over the declaration of the source array, you can #include <stdalign.h>and then declare alignas(uint32_t) uint8_t bytes[]. The classic solution is to declare both the byte array and the 32-bit values as members of a unionand type-pun between them. It is also safe to use pointers obtained from malloc(), since these are guaranteed to be suitably-aligned.

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

回答by F. Mercado

This is one solution:

这是一种解决方案:

/* 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;
}

回答by dimcha

One more solution:

另一种解决方案:

u32 ip;

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

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

Here we use result of in4_ptonfunction (ip) without any additional variables and castings.

这里我们使用in4_pton函数 ( ip) 的结果,没有任何额外的变量和强制转换。