我在写一些软件,其中每一位必须是准确的(这是针对CPU),所以__packed是非常重要的。

typedef union{
uint32_t raw;
struct{
    unsigned int present:1;
    unsigned int rw:1;
    unsigned int user:1;
    unsigned int dirty:1;
    unsigned int free:7;
    unsigned int frame:20;
} __packed;
}__packed page_union_t;

这是我的结构和联合。但是,它没有工作:

page_union_t p; //.....
//This:
p.frame=trg_page;
p.user=user;
p.rw=rw;
p.present=present;
//and this:
p.raw=trg_page<<12 | user<<2 | rw<<1 | present;

应该创建相同UINT32。但他们并没有创造同样的事情。

有什么我看不出是错我的工会?

有帮助吗?

解决方案

您结构仅具有31位

其他提示

AFAIK,其中在结构中的比特被存储的顺序是由C99标准未定义的(和C89标准太)。最可能的是位来自你所期望的相反的顺序。

您应该表现出你得到的结果,以及你所期望的结果 - 这将帮助我们诊断。你用你运行的编译器和平台也可能是显著。


在的MacOS X 10.4.11(的PowerPC G4),此代码:

#include <inttypes.h>
#include <stdio.h>

typedef union
{
        uint32_t raw;
        struct
        {
                unsigned int present:1;
                unsigned int rw:1;
                unsigned int user:1;
                unsigned int dirty:1;
                unsigned int free:7;
                unsigned int frame:20;
        };
} page_union_t;

int main(void)
{
        page_union_t p = { .raw = 0 }; //.....
        unsigned trg_page = 0xA5A5A;
        unsigned user = 1;
        unsigned rw = 1;
        unsigned present = 1;

        p.frame = trg_page;
        p.user = user;
        p.rw = rw;
        p.present = present;

        printf("p.raw = 0x%08X\n", p.raw);

        p.raw = trg_page<<12 | user<<2 | rw<<1 | present;
        printf("p.raw = 0x%08X\n", p.raw);

        p.raw <<= 1;
        printf("p.raw = 0x%08X\n", p.raw);
        return(0);
}

产生所示的结果:

p.raw = 0xE014B4B4
p.raw = 0xA5A5A007
p.raw = 0x4B4B400E

使用的字段的顺序颠倒,结果是更接近可解释:

#include <inttypes.h>
#include <stdio.h>

typedef union
{
        uint32_t raw;
        struct
        {
                unsigned int frame:20;
                unsigned int free:7;
                unsigned int dirty:1;
                unsigned int user:1;
                unsigned int rw:1;
                unsigned int present:1;
        };
} page_union_t;

int main(void)
{
        page_union_t p = { .raw = 0 }; //.....
        unsigned trg_page = 0xA5A5A;
        unsigned user = 1;
        unsigned rw = 1;
        unsigned present = 1;

        p.frame = trg_page;
        p.user = user;
        p.rw = rw;
        p.present = present;

        printf("p.raw = 0x%08X\n", p.raw);

        p.raw = trg_page<<12 | user<<2 | rw<<1 | present;
        printf("p.raw = 0x%08X\n", p.raw);

        p.raw <<= 1;
        printf("p.raw = 0x%08X\n", p.raw);
        return(0);
}

这给出结果:

p.raw = 0xA5A5A00E
p.raw = 0xA5A5A007
p.raw = 0x4B4B400E

在第一结果具有E作为最后的十六进制数字,因为至少显著位没有被使用,因为该位字段结构具有限定只有31位..

如果位的精确位置的问题,你最安全的选择是明确的填料和结构的拆包成无符号的字符阵列。任何其他太依赖于实现的。

有关参考谁的人可能会发现这个问题,尝试packed属性:

struct __attribute__((packed)){

}

您不提,你事先清理出结构的位,你确定你是不是在第一种情况下遗留下来的垃圾位结束了?

// maybe try this
page_union_t p = {0};
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top