how to cast uint8_t array of 4 to uint32_t in c

Given the need to get uint8_t values to uint32_t, and the specs on 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);

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 type2 is char (or unsigned char or const char etc.), but if type2 is any other type (uint32_t in your example) it's against the standard and may introduce bugs to your code if you compile with -O2 or -O3 optimization.

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:

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

So you can't avoid using the shifts.

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


If v4full is a pointer then the line

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 v4 is itself a pointer to a uint8 array. I realize I am extrapolating from incomplete information…

EDIT since 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 04030201 instead of 01020304 as 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.

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

Tags:

C

Casting