当前位置:网站首页>c语言位段

c语言位段

2022-08-09 07:08:00 BSP初级小学僧

我们在存储一些数据有时候并不需要一个完整字节,可能只需要使用几个bit位存储数据即可,所以为了节省内存空间,C语言提供“位段”的数据结构,可以把一个(或多个)字节分成几个不同位数(bit)区域,这样就可以把几个对象放到不同的区域然后用一个(或多个)字节来表示。

位段声明形式和定义结构体相似,但它的成员是一个或多个位的字段,其结构为:

struct 结构名 
{
     位段列表;
};

struct bit_sizeof
	{
		int a:2;//00 01 10 11
		int b:3;
		int c:8;
		int d:30;	
	};

其中位段列表形式如下,其中位段长度指的是某个成员变量所占用的二进制位数(bit):

类型说明符 位段名:位段长度
一个位段声明的例子1:

struct CHAR
{
    unsigned ch     : 7;    
    unsigned font     : 8;    
    unsigned len     : 9;
}ch1;

上例中,每个成员变量位宽大小分别是7bit、8bit、9bit,使用sizeof()得出所占大小为4字节,因为是成员类型相同,所以后面的成员紧邻前一个成员存储,总共24bit,不满一个unsigned 类型长度,所以大小为4字节。

需要注意的是,位段的宽度不能超过它所依附的数据类型的长度,也就是说每个成员变量的类型都会有大小限制,如果“:”后面的数据超过了这个长度,运行后输出的该值可能出错,需要注意。另外,若成员的长度大于位段宽度则可能输出不完整,如下例2:

	struct bs
    {
		unsigned char ch1 	: 8;	
		unsigned char ch2 	: 6;	
		//unsigned char ch3   : 9; //位段宽度超过数据类型宽度,gcc编译出错
    }test;

1.当位段成员的类型相同时,位段成员会挨着存储,若存储后位段成员的bit位宽之和小于类型大小,则sizeof()该段位为类型大小,若位宽之和总大小大于类型大小,则sizeof()该段位大小为,则其偏移量为类型大小的整数倍。

该例中,位段成员位宽之和小于该类型大小,sizeof()该位段为4;

  	struct bs
    {
        int a: 1;
        int b: 2;  
        int c: 3;
    } ; 

该例中,位段成员位宽之和大于该类型大小,sizeof()该位段为8

2.当相位段员的类型不同时,不同系统环境sizeof()该段位可能会有不同的大小结果。

该例中,gcc下运行sizeof()该位段大小为4,表明三个位段成员会挨着存储;在vs2010下运行sizeof()该位段大小为8,表明前两个位段成员挨着存储,后一个位段成员与前两个成员类型不同,所以另起一个单元存储。

  	struct bs
    {
        int a	: 1;
        int b	: 4;  
        char c	: 4;
    } ;

 

#include <stdio.h>
void bit_size(void);
int main()
{
	bit_size();
	return 0;
}

void bit_size(void)
{
	struct bit_sizeof
	{
		int a:2;//00 01 10 11
		int b:3;
		int c:8;
		int d:30;	
	};
	struct bit_sizeof bit_01;
	
	bit_01.a=3;//初始化 
	unsigned char *p=&bit_01;//字符型指针指向bit_01的首地址
	printf("*p=%#p\n",p);//地址位置 
	printf("*p=%u\n",*p);
	bit_01.b= 0x1E;
	printf("*p=%u\n",*p);
} 

运行结果:

作业1: 请编写一个程序将一个整型变量右移4位,并以二进制的形式输出移位前和移位后的数值,看看你的系统是补0还是补1?

#include <stdio.h>

int main()
{
	int a;
	printf("请输入一个整数:\n");
	scanf("%d",&a);
	int c=a;
	unsigned int b = 0x1<<31;
	for(int i=1;i<=32;i++)
	{
		a & b? putchar('1') : putchar('0');
		a <<= 1;
		if(i%8==0)
			printf(" ");
	}
	c >>= 4;
	printf("\n");
	for(int i=1;i<=32;i++)
	{
		c & b? putchar('1') : putchar('0');
		c <<= 1;
		if(i%8==0)
			printf(" ");
	}
	return 0;
	
/*
请输入一个整数: 
87654321
00000101 00111001 01111111 10110001
00000000 01010011 10010111 11111011
*/	
}

由结果可知:本系统补0

作业2:无符号数左移移位相当于该数乘以2,编写一个函数,接收两个整型变量num和pow作为实参,被掉函数使用移位运算计算num*2\^pow的结果。然后分别以整型和二进制形式输出。

#include <stdio.h>

int main()
{
	int a,b;
	printf("请输入两个整数\n");
	scanf("%d %d",&a,&b);
	change(a,b);
	return 0;
} 

void change(int x,int y)
{
	int z=(x<<1)^y;
	printf("%d\n",z);
	
	unsigned int b = 0x1<<31;
	for(int i=1;i<=32;i++)
	{
		z & b? putchar('1') : putchar('0');
		z <<= 1;
		if(i%8==0)
			printf(" ");
	}
}
原网站

版权声明
本文为[BSP初级小学僧]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_46094737/article/details/126237311