C语言的结构体位定义问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言的结构体位定义问题相关的知识,希望对你有一定的参考价值。

定义下面两个结构体,不知道有啥区别,还有那个冒号代表什么意思呀;请大侠帮忙解答一下;谢谢 typedef struct
uint16_t bit0:1;
uint16_t bit1:1;
uint16_t bit2:1;
uint16_t bit3:1;
uint16_t bit4:1;
uint16_t bit5:1;
uint16_t bit6:1;
uint16_t bit7:1;
uint16_t bit8:1;
uint16_t bit9:1;
uint16_t bit10:1;
uint16_t bit11:1;
uint16_t bit12:1;
uint16_t bit13:1;
uint16_t bit14:1;
uint16_t bit15:1;
BITS16;

typedef struct
uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
uint8_t bit8:1;
uint8_t bit9:1;
uint8_t bit10:1;
uint8_t bit11:1;
uint8_t bit12:1;
uint8_t bit13:1;
uint8_t bit14:1;
uint8_t bit15:1;
BITS16;
这两个写法有什么区别?
上面本质应该都是用了2个字节空间;我想对于上面的写法应该是一样的吧
至少这个写法对于1个位的定义是一样的;是吧?
如果定义
bitx:10;
则uint8_t 这么定义会有问题是吧?因为8位的字节不够分配10个位,只能用uint16_t定义;
当然中间的空隙位是要看下面的位定义加上去会不会超过一个新字节;如果不会则继续添加位定义,直到出现不够新的位定义,才跳转到下一个字节定义位段;
不知道这么理解是否合理;
貌似uint8_t定义小位段(大于1位)会比uint16_t浪费位空间吧?因为需要凑空间,不够得新申请字节空间;
我想我是理解了,谢谢
另外uint8_t和uint16_t是个标准定义;

按照名字定义,u无符号 int 整形,数字 8 16,表示多少位的整形, 

1字节     uint8_t

2字节     uint16_t

4字节     uint32_t

8字节     uint64_t

详情参考:http://www.cnblogs.com/baochun968/archive/2011/10/19/2218008.html


bit0:1这句话定义了一个位域,bit0是该位域的域名,而且bit0只占用一个位。

位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。为了节省存储空间,并使处理简便,C语言提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。

参考:http://zhidao.baidu.com/question/391684179.html


所以上面的结构体,一个元素属性占一位,前面的是2字节,后面也是两个字节。本质上没有区分吧


常规下可以这样测试上面的代码


#include<stdio.h>
typedef unsigned short uint16_t ;
typedef unsigned char uint8_t ;
typedef struct

uint16_t bit0:1;
uint16_t bit1:1;
uint16_t bit2:1;
uint16_t bit3:1;
uint16_t bit4:1;
uint16_t bit5:1;
uint16_t bit6:1;
uint16_t bit7:1;
uint16_t bit8:1;
uint16_t bit9:1;
uint16_t bit10:1;
uint16_t bit11:1;
uint16_t bit12:1;
uint16_t bit13:1;
uint16_t bit14:1;
uint16_t bit15:1;
BITS161;
typedef struct

uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
uint8_t bit8:1;
uint8_t bit9:1;
uint8_t bit10:1;
uint8_t bit11:1;
uint8_t bit12:1;
uint8_t bit13:1;
uint8_t bit14:1;
uint8_t bit15:1;
BITS162;
int main()
printf("%d,%d",sizeof(BITS161),sizeof(BITS162));
return 0;


输出为2,2,表示结构体都是两个字节。但是如果typedef unsigned int uint16_t ; 就是用通常的4字节整形表示uint16_t ,上面的结构体至少要一个int长度 ,输出为4,2

参考技术A 1.我认为uint16_t这是你定义的一个新类型
typedef unsigned short uint16_t; /*就是定义无符号短整型为 uint16_t*/
typedef unsigned char uint8_y; /*定义无符号char型为 uint8_t*/
两个结构体中只有这地方不同,对于第二个结构提,因为char型,只有8位,当超过8bit时,会自动的申请新的字节进行存储,因此第二个字节使用2个1字节存储,而第一个结构体使用1个2字节存储。

2.对于冒号,这是C语言中位域的用法,有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。
例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示
具体例子如下:
#include <stdio.h>

typedef unsigned char u8;

/*定义新类型,这个新类型由4部分组成,每部分只占无符号char型8bit
中的几bit*/
typedef struct _my_bit_

u8 one:1;
u8 two:2;
u8 three:3;
u8 four:2;
mybitfiled;

int main()

mybitfiled mybit;
/*注意位域分配的位个数,例如one只分配了1bit,那么mybit.one只能为1或0,
如果输入2的话,那么会提示将多余部分给删掉的,意思只能取最后1bit的信息*/

mybit.one = 1;
mybit.two = 2;
mybit.three = 3;
mybit.four = 1;
printf("sizeof(mybit) = %d,%d %d %d %d\n",sizeof(mybit),mybit.one,mybit.two,mybit.three,mybit.four);

return 0;
参考技术B 前面用一个2字节整型16位比特来做数据结构,后面用2个1字节整型16位比特来做数据结构。

uint16_t bit0:1的意思是取16位比特中的一位用于存放bit0的值,其他类推。
这两种定义方式的区别,主要在小头字节序的CPU上有差别,小头的话,实际内存空间里两种定义方法两字节的位置反一反。
参考技术C uint16_t 是16位无符号数,uint8_t看起来是8位无符号数,这样的话第二种定义是错误的,一共就8位,不能定义16个单独的bit,bit0:1意思是,起始位bit0,占用1位,bit0:3意思是起始位bit0,占用bit0,bit1,bit2共3位

以上是关于C语言的结构体位定义问题的主要内容,如果未能解决你的问题,请参考以下文章

C语言自定义类型一网打尽(结构体位段/位域枚举联合体)

C语言的结构体位定义问题

C语言结构体中冒号的作用——位域

C语言用例子一次性讲清楚结构体和联合体区别,xdm看过来!

c语言 关于位域的使用

梦开始的地方 —— C语言(枚举+位段+联合体)