当前位置:网站首页>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(" ");
}
}
边栏推荐
- Invoker 2019CCPC秦皇岛站I题 简单DP
- postgresql窗口功能
- 【sqlite3】sqlite3.OperationalError: table addresses has 7 columns but 6 values were supplied
- rsync:recv_generator: mkdir (in backup) failed:Permission denied (13) |failed to set times on '.'
- dp学习笔记
- Quectel EC20 4G module dial related
- 半导体新能源智能装备整机软件系统方案设计
- imageio读取.exr报错 ValueError: Could not find a backend to open `xxx.exr‘ with iomode `r`
- Forest Program dfs+tanjar仙人掌
- 2017.10.26模拟 b energy
猜你喜欢
基于布朗运动的文本生成方法-LANGUAGE MODELING VIA STOCHASTIC PROCESSES
(本章节完结)排序第五节——非比较排序(计数排序+基数排序+桶排序)(附有自己的视频讲解)
差分约束-图论
The water problem of leetcode
错误:为 repo ‘oracle_linux_repo‘ 下载元数据失败 : Cannot download repomd.xml: Cannot download repodata/repomd.
搭载开源鸿蒙系统的嵌入式XM-RK3568工业互联方案
Change Jupyter Notebook default open directory
高项 04 项目整体管理
jmeter concurrency and some limitations of the press
学习小笔记---机器学习
随机推荐
vim 程序编辑器的基本操作(积累)
图论,二叉树,dfs,bfs,dp,最短路专题
先序遍历,中序遍历,后序遍历,层序遍历
搭载开源鸿蒙系统的嵌入式XM-RK3568工业互联方案
分布式事务的应用场景
The AD in the library of library file suffix. Intlib. Schlib. Pcblib difference
细谈VR全景:数字营销时代的宠儿
数据一致性架构
Change Jupyter Notebook default open directory
A brief introduction to microservice architecture
Singleton DCL (double check the lock) full han mode and the hungry
Rsync常见错误
The Integer thread safe
神经网络优化器
Invoker 2019CCPC秦皇岛站I题 简单DP
【转载】Deep Learning(深度学习)学习笔记整理
【报错】Root Cause com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
tianqf的解题思路
Codeforces Round #359 (Div. 2) C. Robbers' watch 暴力枚举
学习小笔记---机器学习