【问题标题】:Are bits in the structure guaranteed结构中的位是否得到保证
【发布时间】:2019-08-01 11:02:11
【问题描述】:

我有一个与结构位字段相关的问题,请参阅下文,因为我对应该使用哪些关键字来最好地描述我的问题有点不知所措:

上下文:我正在为 MIPS R3000A 汇编指令编写反汇编程序,该指令在 2000 年初用于 Playstation 程序。

问题:我想知道是否在此代码中:

struct Instruction {
    u32 other:26;
    u32 op:6;
};

//main:
Instruction instruction = *(Instruction*)(data + pc);
printf("%02x\n", instruction.op);

保证所有使用小字节序的编译器总是使用 op:6 位域来存储前 6 个 MSB 吗? (这有点反直觉,你会假设最后 6 位存储在 op 位字段中)

它是以下代码的替代方案:

static uint32_t get_op_code(uint32_t data) {
    uint16_t mask = (1 << 6) - 1;
    return (data >> 26) & mask;
}

//main:
uint32_t instruction = *(uint32_t*)(data + pc);
uint32_t op = get_op_code(instruction);
printf("%02x\n", op);

在我这边工作得很好,使用结构方法似乎稍微快一点,更不用说更直观和清晰,但恐怕不能保证前 6 位存储在结构的第二个位域“op”。

【问题讨论】:

    标签: c structure mips endianness mips32


    【解决方案1】:

    C 标准不保证位域的排列方式。它确实需要每个实现来定义它,所以它应该在编译器的文档中。根据 C 2018 6.7.2.1 11:

    实现可以分配任何大到足以容纳位字段的可寻址存储单元。如果有足够的空间,结构中紧跟在另一个位域之后的位域将被打包到同一单元的相邻位中。如果剩余空间不足,则将不适合的位域放入下一个单元还是与相邻单元重叠是实现定义的。单元内位域的分配顺序(高位到低位或低位到高位)是实现定义的。未指定可寻址存储单元的对齐方式。

    【讨论】:

    • 好的,谢谢我正要回答我自己的问题,我找到了这个; “一个单元内位域的分配顺序(高阶到低阶或低阶到高阶)是实现定义的。” c0x.coding-guidelines.com/6.7.2.1.html 我会为此给你功劳;)回答这个问题的不是更多的 6.7.2.1 12 吗?另外你为什么会建议呢?可能保留第二种方法?
    • @AntoninGAVREL:是的,如果您需要保证 C 中位域的顺序,您必须使用位运算符而不是位域。但是,许多编译器提供预处理器宏来指示版本和功能,因此另一种方法是编写预处理器语句来测试是否使用了已知的编译器和位域顺序。然后代码可以有条件地编译以以一种或另一种顺序定义结构(如果它识别出正在使用的编译器)或发出带有#error 的消息(如果它不识别编译器)。
    • 嗨@Eric,如果您有时间,您能否展示一个快速、简约的建议示例?
    • @AntoninGAVREL:我手头没有关于 GCC 或其他编译器如何指示预处理器宏中位域顺序的信息。 GCC documentation 表示它由 ABI 确定,因此可能必须测试暗示正在使用哪个 ABI 的预处理器宏,或者可能有直接的预处理器宏来报告顺序,或者可能没有。您可以输入另一个有关此问题的 Stack Overflow 问题。
    猜你喜欢
    • 1970-01-01
    • 2016-07-26
    • 2012-01-22
    • 2015-08-13
    • 2021-03-16
    • 2018-09-25
    • 2021-01-27
    相关资源
    最近更新 更多