结构体之位域详解(C语⾔结构体中的冒号)
在数据存储时,有些时候并不需要占⽤⼀个完整的字节,⽐如数值 1, 只需要占⽤⼀个bit(⼆进制 1); 数值2 只需占⽤2个bit (⼆进制 10)。 在这样不需要太多bit来表⽰⼀个数值时候,为了节省存储空间,C语⾔提供了⼀种数据结构,称之为“位域”,允许在程序中按照其域名进⾏操作,这样就可以使得多个不同的对象⽤⼀个字节中的若⼲个⼆进制位域来表⽰。
以下具体介绍位域相关知识点
1.含位域的结构体基本定义
struct位域结构名
{
数据类型说明符位域名:位域长度;
};
2.位域的结构体sizeof如何计算⼤⼩?
以实际代码为例,下⾯做两种情况下的具体分析,
此段代码为打印位域结构体数据的⼤⼩代码,以下列出的各种情况都由此段代码打印得出的结果。
int main()
{
/**1. 声明⼀个位域结构体threshold_test*/
threshold_struct threshold_test;
/** 2. 打印⼤⼩*/
printf("The struct \"threshold_test\" size = %d\n",sizeof(threshold_test));
return0;
}
1. 数据类型排序改变,位域长度不变
1. (排序情况: int,int,char)
typedef struct struct_threshold_test
{
int VariableOne:1;// 取1位
int VariableTwo:4;// 取4位
char VariableThree:2;// 取2位
}threshold_struct;
打印情况:
The struct"threshold_test" size =8
2. (排序情况: int,char,int)
typedef struct struct_threshold_test
{
int VariableOne:1;// 取1位
char VariableThree:2;// 取2位
int VariableTwo:4;// 取4位
}threshold_struct;
打印情况:
The struct"threshold_test" size =12
3. (排序情况: char,int,int)
int VariableTwo:4;// 取4位
}threshold_struct;
打印情况:
The struct"threshold_test" size =8
2. 数据类型排序不变,位域长度改变
1. (位域长度依次为: 1, 4, 2)
typedef struct struct_threshold_test
{
int VariableOne:1;// 取1位
int VariableTwo:4;// 取4位
char VariableThree:2;// 取2位
}threshold_struct;
打印情况:
The struct"threshold_test" size =8
c语言中struct2. (位域长度依次为: 16, 16, 8)
typedef struct struct_threshold_test
{
int VariableOne:16;// 取16位
int VariableTwo:16;// 取16位
char VariableThree:8;// 取8位
}threshold_struct;
打印情况:
The struct"threshold_test" size =8
3. (位域长度依次为: 16, 17, 8)
typedef struct struct_threshold_test
{
int VariableOne:16;// 取16位
int VariableTwo:17;// 取17位
char VariableThree:8;// 取8位
}threshold_struct;
打印情况:
The struct"threshold_test" size =12
3.根据以上代码的验证可以得出以下计算位域结构体数据的⽅法:
(1)第⼀步,根据结构体数据⾥⾯所有的基本数据类型中占⽤存储空间最⼤的基本数据类型作字节对齐。
(2)第⼆步,如果相邻的基本数据类型⼀致,则查看两者的位域长度之和是否⼤于此数据类型的存储空间,⼤于则两者之和的⼤⼩为两个此类型的存储空间;⼩于等于则两者之和的⼤ ⼩为单个此类型的存
储空间。
如果相邻的数据类型不⼀致,则以占⽤存储空间最⼤的基本数据类型作字节对齐。
(3)第三步, 根据第⼀、⼆步计算总⼤⼩。
举例分析如何计算:
char VariableThree:2;// 取2位
}threshold_struct;
(1)第⼀步:上⾯所有基本数据类型中,存储空间最⼤的为int类型,占⽤字节数为4
(2)第⼆步: VariableOne, VariableTwo变量两者相邻,均为int类型,其位域之和为1+4=5;5<(sizeof(int)),所以变量VariableOne和VariableTwo的占⽤存储空间
为sizeof(int),即4字节。
(3)第三步: VariableThree变量类型为char,已知sizeof(char)<sizeof(int),所以按照int类型对齐,即占⽤空间为4字节。所以这个位域的结构体数据总⼤⼩为
4+4=8个字节。
3.位域的结构体数据如何进⾏printf打印 ?
1. ⾸先,我们来看⼀下以下代码的打印值
typedef struct struct_threshold_test
{
int VariableOne:1;// 取1位
int VariableTwo:4;// 取4位
char VariableThree:2;// 取2位
}threshold_struct;
int main()
{
/
**1. 声明⼀个位域结构体threshold_test*/
threshold_struct threshold_test;
/** 2. 赋值*/
threshold_test.VariableOne =1;// ⼆进制表⽰ 1
threshold_test.VariableTwo =15;// ⼆进制表⽰ 1111
threshold_test.VariableThree =2;// ⼆进制表⽰ 10
/** 3. 打印值*/
printf("threshold_test.VariableOne = %d\n",threshold_test.VariableOne);
printf("threshold_test.VariableTwo = %d\n",threshold_test.VariableTwo);
printf("threshold_test.VariableThree = %d\n",threshold_test.VariableThree);
return0;
}
//打印情况:
threshold_test.VariableOne =-1
threshold_test.VariableTwo =-1
threshold_test.VariableThree =-2
奇怪,为什么我的打印不是 1,15,2呢?怎么会是 -1, -1, -2呢? 明明 1的⼆进制就是⼀个bit(1), 15的⼆进制是4个bit(1000), 2的⼆进制是2个bit( 10). 怎么%d打印的跟我设置的
变量不同呢
其实原因在于,在有符号的基本数据类型定义的变量中,需要有⼀个bit来保存正负的标志, 要想打印正常,只需要将上述变量的位域长度增加1,即可正常打印。
当然啦,也可以将变量定义为⽆符号类型,就不需要增加1个位也可以进⾏正常打印,如下:
unsigned int VariableOne:1;//
unsigned int VariableTwo:4;//
unsigned char VariableThree:2;//
}threshold_struct;
int main()
{
/**1. 声明⼀个位域结构体threshold_test*/
threshold_struct threshold_test;
/** 2. 赋值*/
threshold_test.VariableOne =1;// ⼆进制表⽰ 1
threshold_test.VariableTwo =15;// ⼆进制表⽰ 1111
threshold_test.VariableThree =2;// ⼆进制表⽰ 10
/
** 3. 打印值*/
printf("threshold_test.VariableOne = %d\n",threshold_test.VariableOne); printf("threshold_test.VariableTwo = %d\n",threshold_test.VariableTwo); printf("threshold_test.VariableThree = %d\n",threshold_test.VariableThree);
return0;
}
//打印情况:
threshold_test.VariableOne =1
threshold_test.VariableTwo =15
threshold_test.VariableThree =2
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论