6

我正在编写一些软件,其中每一位都必须准确(它用于 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。但他们不会创造同样的东西。

我的工会有什么我看不到的地方吗?

4

5 回答 5

10

您的结构只有 31 位

于 2009-06-11T02:44:05.043 回答
6

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 位。

于 2009-06-11T02:46:27.050 回答
2

如果位的确切位置很重要,那么您最安全的选择是将结构显式打包和解包到一个无符号字符数组中。其他任何东西都太依赖于实现了。

于 2009-06-11T03:20:30.977 回答
2

为了参考可能会发现这个的任何人,请尝试打包属性:

struct __attribute__((packed)){

}
于 2017-04-07T04:31:22.800 回答
0

你没有提到你事先清除了结构的位,你确定你没有在第一种情况下留下垃圾位吗?

// maybe try this
page_union_t p = {0};
于 2009-06-11T02:45:03.093 回答