Linux c 中指定位字段的结构体及其在联合体的用处
这是第一次在csdn上写文章,分享一个我在使用联合体时的一个新颖的经历。c语言联合体定义:几种不同类型的变量存放到同一段内存单元中,也就是使用覆盖技术,几个变量相互覆盖,这几种变量共同占用一段内存,在c语言中,这被称为“共用体”、“联合体”。(来源自360百科)
先看如下代码:
union samp_union{
u32_t raw;
struct __bits{
u32_t member1 : 1;
u32_t member2 : 3;
u32_t member3 : 3;
u32_t reserved : 24;
}bits;
};
void samp_function(u32_t parameter)
{
union samp_union my_union;
my_union = (union samp_union)parameter;
printf("member1=%d\n",my_union.bits.member1);
printf("member2=%d\n",my_union.bits.member2);
printf("member3=%d\n",my_union.bits.member3);
printf("reserved=%d\n",my_union.bits.reserved);
return;
}
int main()
{
union samp_union test_union;
test_union.bits.member1 = 0x01;
test_union.bits.member2 = 0x04;
test_union.bits.member3 = 0x08;
test_union.bits.reserved = 0x00;
samp_function(test_union.raw);
return 0;
}
以前没看过这种用法的朋友肯定有不少疑惑,会以为联合体samp_union包含了两个成员,一个u32_t 类型的raw和一个struct __bits类型的bits,然后bits包含了4个u32_t类型的成员,所以该联合体的大小是由bits的大小决定的,一共4*4=16个字节大小。
如果到此为止的话也还好理解,可是看到给函数samp_function()传参的方式就有点百思不得其解了——只传了联合体的raw成员的值,然后通过该值强制转换成 union samp_union类型?如果传给函数的是个地址,后面通过地址类型转换得到整个联合体,这样的话没什么疑惑,可是形参parameter仅仅是一个u32_t 类型的数据…
后来问了资深人士,解答如下:
以上联合体的用法是linux c中的用法,联合体还是原来的联合体,没什么特别的,特殊的是struct __bits结构体,该结构体指定了每个成员的位字段,每个成员的位数加起来不超过32位,所以该结构体的大小仅为4个字节。member1成员占了1个bit,member2成员占了3个bit,member3和reserved成员分别占了3个bit和24个bit,所以samp_union联合体的raw成员和bits成员是处在同一地址空间的。把raw传给参数parameter,实际上是把整个struct __bits 结构体赋给参数。