将结构体转换为整数

15

有没有一种简单的方法将结构体转换为uint64_t或任何其他类型的整数,假设该结构体小于或等于int的大小? 我能想到的唯一解决方案是使用union,但我从来不喜欢他们。

让我添加一个代码片段来澄清:

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;

现在,我该如何将 some_struct 强制转换为 uint32_t 寄存器以捕获其位顺序。

希望这样能更清晰一些。


7
不喜欢工会?工会可以以明确、易于维护的方式实现你想要做的事情。这有什么只是“一般般”的呢? - Carey Gregory
1
请提供更多信息,否则我无法回答这个问题。 - djechlin
2
有一种方法可以将结构体指针转换为整型指针,但很可能会导致未定义的行为。如果你更喜欢未定义的行为而不是联合体,这个链接展示了如何进行黑客攻击:http://ideone.com/7E3eZ。 - Sergey Kalinichenko
1
为什么只在这里使用memcpy?你可以使用某种宏编辑器来修改源代码,以便在所有赋值操作中使用memcpy()调用<g>。 - Martin James
memcpy不会受到对齐的影响吗? - rubenvb
显示剩余6条评论
5个回答

32

我刚刚遇到了同样的问题,我用类似这样的联合解决了它:

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;

问候,Alex


3
警告:在某些情况下,使用某些编译器可能会引发未定义的行为。请参考Andrew Henle的评论。如果您要使用我的答案,请了解-fno-strict-aliasing编译器标志。
您可以将对象的指针转换为所需的类型,然后对其进行解引用。还要考虑您的平台的字节顺序。
使用uint16_t的简短示例:
*(uint16_t *)&my_struct

详细示例使用 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;
}

2
这个答案违反了严格别名规则,并导致未定义的行为。如果结构体的对齐方式不适合uint16_t,它也可能引发未定义的行为。两个层次的未定义行为都是不好的。 - Andrew Henle

3

一种非便携式的解决方案:

struct smallst {
  int a;
  char b;
};

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

你可能会遇到问题,例如在小端机器上打包结构体,在大端机器上解包结构体。

memcpy() 是最具可移植性的解决方案之一... - Andrew Henle

0

你可以使用指针,这会很容易。 例如:

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;

希望它有所帮助。

1
这将需要在任何符合标准的编译器中进行类型转换,并且在许多编译器上还需要使用“-fno-strict-aliasing”或某些类似选项。 - supercat

-1

问题标记为 [tag:c]。C语言没有 static_castreinterpret_cast 或用户定义的转换函数。 - ad absurdum
虽然这个链接可能回答了问题,但最好在这里包含答案的关键部分,并提供链接作为参考。仅有链接的答案如果链接页面发生变化,就会失效。- 来自评论 - user16217248

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接