在位域上转换 uint64_t

标签 c casting endianness bit-fields strict-aliasing

我找到了将位字段用于网络消息的代码。我想知道转换 bitfield_struct data = *(bitfield_struct *)&tmp; exaclty 的作用以及它的语法如何工作。不会违反严格的别名规则吗?这是部分代码:

typedef struct  
{
    unsigned      var1    : 1;
    unsigned      var2    : 13;
    unsigned      var3    : 8;
    unsigned      var4    : 10;
    unsigned      var5    : 7;
    unsigned      var6    : 12;
    unsigned      var7    : 7;
    unsigned      var8    : 6;

} bitfield_struct;

void print_data(u_int64_t * raw, FILE * f, int no_object)
{
    uint64_t tmp = ntohll(*raw);

    bitfield_struct data = *(bitfield_struct *)&tmp;

    ...
}

最佳答案

Won't it violate the strict aliasing rule?

是的,所以代码会调用未定义的行为。它也非常不便携:

  • 我们不知道给定系统使用的称为“可寻址存储单元”的抽象项的大小。它不一定是 64 位,因此理论上可能会在位字段中隐藏填充和其他令人讨厌的东西。 64 位无符号 很可疑。

  • 我们也不知道位字段是否使用与 uint64_t 相同的位顺序。我们也不知道它们是否使用相同的字节顺序。

如果需要访问uint64_t的各个位(字段),我建议使用按位移位来实现,因为这使得代码即使在不同的字节序架构之间也可以完全移植。那么您也不需要不可移植的 ntohll 调用。

关于在位域上转换 uint64_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59321863/

相关文章:

c++ - 错误 : invalid conversion from 'unsigned char*' to 'const signed char*'

php - 将主机字节顺序(小端)中的字符串转换为网络字节顺序(大端)

使用 cryptoauthlib 配置 ATEC608A

c# - 为什么 x = x + 100 与编译为相同 IL 的 x += 100 的处理方式不同?

c - 将 void 与 printf 函数一起使用

c# - 继承和转换错误(通用接口(interface))

Ruby 如何将 32 位整数转换为网络字节序?

java - 按位运算的结果是否取决于 Java 中的字节顺序?在 C 或 C++ 中呢?

c - 在C中对文件中的 float 进行排序

c - mruby 中的最小静态编译