我正在编写一些软件,其中每个位必须精确(它是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。但他们并没有创造同样的东西。
我的工会有什么我看不到的错误吗?
答案 0 :(得分:8)
你的结构只有31位
答案 1 :(得分: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位定义..
答案 2 :(得分:2)
如果位的确切位置很重要,那么最安全的选择是显式打包并将结构解压缩到unsigned char数组中。其他任何东西都与实现有关。
答案 3 :(得分:2)
有关可能找到此内容的任何人的参考,请尝试打包属性:
struct __attribute__((packed)){
}
答案 4 :(得分:0)
你没有提到你是在事先清除结构的各个部分,你确定你在第一种情况下没有留下垃圾比特吗?
// maybe try this
page_union_t p = {0};