GoTTimw
GoTTimw

Reputation: 2430

Casting struct into int

Is there a clean way of casting a struct into an uint64_t or any other int, given that struct in <= to the sizeof int? The only thing I can think of is only an 'ok' solution - to use unions. However I have never been fond of them.

Let me add a code snippet to clarify:

typedef struct {
uint8_t field: 5;
uint8_t field2: 4;
/* and so on... */
}some_struct_t;

some_struct_t some_struct;
//init struct here

uint32_t register;

Now how do i cast some_struct to capture its bits order in uint32_t register.

Hope that makes it a bit clearer.

Upvotes: 16

Views: 34951

Answers (5)

Amit Ferman
Amit Ferman

Reputation: 37

Using a user-defined static_cast conversion is simpler than both union and reinterpret_cast/pointer casting: https://en.cppreference.com/w/cpp/language/cast_operator

Upvotes: -2

Den Avrondo
Den Avrondo

Reputation: 107

Warning: It can invoke undefined behaviour under certain circumstances using certain compilers. See Andrew Henle's comment. If you will use my answer, learn about -fno-strict-aliasing compiler flag.

You can cast object's pointer to desired type and then dereference it. Also consider your plaftorm's endianness.

Short example using uint16_t:

*(uint16_t *)&my_struct

Detailed example using uint16_t:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    uint8_t field1;
    uint8_t field2;
} MyStruct;

int main() {
    MyStruct my_struct = {0xFA, 0x7D};
    uint16_t num_my_struct = *(uint16_t *)&my_struct;
    printf("%X \n", num_my_struct);  // 7DFA (little-endian machine)

    return 0;
}

Upvotes: 4

omry155
omry155

Reputation: 9

you can use pointers and it will be easy for example:

struct s {
    int a:8;
    int b:4;
    int c:4;
    int d:8;
    int e:8; }* st;

st->b = 0x8;
st->c = 1;
int *struct_as_int = st;

hope it helps

Upvotes: 0

Alex Zeffertt
Alex Zeffertt

Reputation: 1572

I've just hit the same problem, and I solved it with a union like this:

typedef union {
    struct {
        uint8_t field: 5;
        uint8_t field2: 4;
        /* and so on... */
    } fields;
    uint32_t bits;
} some_struct_t;

/* cast from uint32_t x */
some_struct_t mystruct = { .bits = x };

/* cast to uint32_t */
uint32_t x = mystruct.bits;

HTH, Alex

Upvotes: 35

perreal
perreal

Reputation: 97938

A non-portable solution:

struct smallst {
  int a;
  char b;
};

void make_uint64_t(struct smallst *ps, uint64_t *pi) {
  memcpy(pi, ps, sizeof(struct smallst));
}

You may face problems if you, for example, pack the struct on a little-endian machine and unpack it on a big-endian machine.

Upvotes: 4

Related Questions