C语言位域——精妙使用内存
参考链接 https://blog.csdn.net/yanbober/article/details/8697967 https://blog.csdn.net/Tommy_wxie/article/details/43529407
我们都知道信息的存取在高级语言中最小是Byte,以字节为单位的,虽然C语言提供了位操作符&,|,~,<< >>可以对一个整数进行位操作,但是并没有对内存进行优化。现实生活中我们常常需要一个标志值真或者假,即可以用二进制0或者1表示,这种情况很常见,如开关,过程控制、参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进制位,基于此,C语言支持位域定义可以帮我们解决这个问题。
C语言允许在结构体(联合体)中以位为单位来指定其成员变量所占的内存单元,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。
定义:
位域定义与结构定义相仿,其形式为:
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
type [var]:digits
其中,type只能为int,unsigned int,signed int三种类型(int型能不能表示负数视编译器而定,比如VC中int就默认是signed int,能够表示负数)。位段名称var是可选参数,即可以省略。digits表示该位段所占的二进制位数。
使用位段需注意一下几点:
1)位段的类型只能是int,unsigned int,signed int三种类型,不能是char型或者浮点型;
2)位段占的二进制位数不能超过该基本类型所能表示的最大位数,比如在VC中int是占4个字节,那么最多只能是32位;
3)无名位段不能被访问,但是会占据空间;
4)不能对位段进行取地址操作;
5)若位段占的二进制位数为0,则这个位段必须是无名位段,下一个位段从下一个位段存储单元(这里的位段存储单元经测试在VC环境下 是4个字节)开始存放;
6)若位段出现在表达式中,则会自动进行整型升级,自动转换为int型或者unsigned int。
7)对位段赋值时,最好不要超过位段所能表示的最大范围,否则可能会造成意想不到的结果。
8)位段不能出现数组的形式。
二位段结构在内存中的存储方式
对于位段结构,编译器会自动进行存储空间的优化,主要有这几条原则:
1)如果一个位段存储单元能够存储得下位段结构中的所有成员,那么位段结构中的所有成员只能放在一个位段存储单元中,不能放在两个位段存储单元中;如果一个位段存储单元不能容纳下位段结构中的所有成员,那么从剩余的位段从下一个位段存储单元开始存放。(在VC中位段存储单元的大小是4字节).
2)如果一个位段结构中只有一个占有0位的无名位段,则只占1或0字节的空间(C语言中是占0字节,而C++中占1字节);否则其他任何情况下,一个位段结构所占的空间至少是一个位段存储单元的大小;
下面以具体例子来讲解:
#include <stdio.h>
#include <iostream>
using namespace std; typedef struct{
unsigned int a:1; //存在一个非0位的位段,则至少占4Byte,注意是至少
}s;
typedef struct {
unsigned _int64 a:33; //这个占8字节
}ss;
typedef struct {
unsigned int :0; //存在一个0位的位段,C编译器占0字节,C++编译器占1字节
}s1;
typedef struct {
unsigned int a:1;
unsigned :0; //下一个位段放在一个新的位段存储单元 ,所以占4+4=8Byte
unsigned int b:2;
}s2;
typedef struct {
unsigned int a:4;
unsigned int b:32; //由于4+32》32,所以b放在一个新的位段中 4+4=8字节
}s3;
typedef struct {
unsigned int a:1;
char b; //这个加起来总共不超过4字节,占一个位段
int c:1;
int d:2;
unsigned int e:2;
}S4;
extern int testBit()
{
S4 s4;
s4.a=1;
s4.b='a';
s4.c=1;
s4.d=2;
s4.e=2;
cout<<s4.a<<"\t"<<s4.b<<"\t"<<s4.c<<"\t"<<s4.d<<"\t"<<s4.e<<endl;
printf("sizeof(s)=%d\nsizeof(s1)=%d\nsizeof(s2)=%d\nsizeof(s3)=%d\nsizeof(s4)=%d\n",
sizeof(s),sizeof(s1),sizeof(s2),sizeof(s3),sizeof(s4));
cout<<sizeof(ss)<<endl;
return 0;
}
以下链接是一个不错的练习体
http://its.nbtvu.net.cn/xhyu/cai_c/c_web/c/c8/c83.htm
下一篇介绍位段在0_1背包中的蛮力法应用案例
C语言位域——精妙使用内存的更多相关文章
- C语言位域
转载自 http://tonybai.com/2013/05/21/talk-about-bitfield-in-c-again/ 再谈C语言位域 五 21 bigwhite技术志 bitfield, ...
- C语言编程程序的内存如何布局
重点关注以下内容: C语言程序在内存中各个段的组成 C语言程序连接过程中的特性和常见错误 C语言程序的运行方式 一:C语言程序的存储区域 由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过 ...
- C语言编程程序的内存怎样布局
在c语言中,每一个变量和函数有两个属性:数据类型和数据的存储类别. C语言中局部变量和全局变量变量的存储类别(static,extern,auto,register) 1. 从变量的作用域划分变量(即 ...
- C语言之数据在内存中的存储
C语言之数据在内存中的存储 在我们学习此之前,我们先来回忆一下C语言中都有哪些数据类型呢? 首先我们来看看C语言中的基本的内置类型: char //字符数据类型 short //短整型 int //整 ...
- C语言 结构体的内存对齐问题与位域
http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...
- 解析C语言结构体对齐(内存对齐问题)
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...
- c语言位域的使用注意事项——数据溢出
c语言可以使用位域来节省变量的空间,例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位.位域的取值范围非常有限,数据稍微大些就会发生溢出,这个字使用keil的使用,keil提 ...
- 【C】C语言位域(位段)详解
作者:李春港 出处:https://www.cnblogs.com/lcgbk/p/14215449.html 目录 一.位域是什么? 二.位域的存储 2.1 相邻成员的类型相同 2.2 相邻成员的类 ...
- C语言再学习之内存对齐
昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...
随机推荐
- 20135239 Linux内核分析 期中总结
期中总结 链接 网易云课堂 MOOC 摘录与实验内容 第一周: http://www.cnblogs.com/20135239-yxlm/p/5216842.html 第二周: http://www. ...
- Android ProgressBar的使用
Android 基础教程之-------Android ProgressBar的使用http://blog.csdn.net/Android_Tutor/article/details/5695170 ...
- Android实现透明的颜色效果(zz)
android Button或者ImageButton背景透明状态设置 设置Button或ImageButton的背景为透明或者半透明 半透明< Button android:backgroun ...
- 解题:CQOI 2013 和谐矩阵
题面 踩踩时间复杂度不正确的高斯消元 首先可以发现第一行确定后就可以确定整个矩阵,所以可以枚举第一行的所有状态然后$O(n)$递推检查是否合法 $O(n)$递推的方法是这样的:设$pre$为上一行,$ ...
- vmware中centos7设置静态IP
1.vmware—>Edit—>Virtual Network Editor,选中vmnet8-Nat设置,查看网关IP 2.在centos中设置: vi /etc/sysconfig/n ...
- 如何设置C++崩溃时生成Dump文件
Dump 文件是进程的内存镜像 , 可以把程序的执行状态通过调试器保存到dump文件中 ; Dump 文件是用来给驱动程序编写人员调试驱动程序用的 , 这种文件必须用专用工具软件打开 , 比如使用 W ...
- 网络中,FIFO、LRU、OPT这三种置换算法的缺页次数
FIFO.LRU.OPT这三种置换算法的缺页次数 转载 由于要考计算机四级网络,这里遇到了问题,就搜了一些资料来解疑. 考虑下述页面走向: 1,2,3,4,2,1,5,6,2,1,2,3,7,6,3 ...
- win7,Ubuntu 12.04 双系统修改启动项顺序三方法
修改启动项顺序的三种方法 本文所涉及的方法都是在Ubuntu的安装时将引导加载程序grub安装在了整个硬盘(即MBR内),即开机以grub引导. 方法1在Ubuntu终端下输入:sudo mv /et ...
- GO_00:Mac之Item2的配置安装
申明:Mac 本上的终端感觉不是那么多好用,以前在 Windows 上操作 Linux 都是通过 XShell 来操作的,界面美观大方.操作使用比较简单.故在 Mac 上也需要有这样一款类似的工具,那 ...
- SQL Server 2008定期的备份数据库--差异+完整
https://www.cnblogs.com/l1pe1/p/7885207.html https://www.cnblogs.com/tylerflyn/p/8051398.html https: ...