- 浏览: 369945 次
- 性别:
- 来自: 苏州
文章分类
- 全部博客 (335)
- C++ (190)
- 设计模式 (43)
- 数据库技术 (5)
- 网络编程 (11)
- 自动化测试 (6)
- Linux (13)
- OpenSSL (10)
- MS Crypt API (5)
- SCM (2)
- English (4)
- Android (10)
- EMV规范 (1)
- Saturn Platform (0)
- C (10)
- SQL (2)
- ASP.NET (3)
- 英语口语学习 (3)
- 调试工具 (21)
- 编译技术 (5)
- UML (1)
- 项目管理 (5)
- 敏捷开发 (2)
- Http Server (6)
- 代码审查、代码分析 (5)
- 面试基础 (10)
- 重点知识 (16)
- STL (6)
- Efficient C++资料 (8)
- 数据结构和算法 (7)
- 读书笔记 (0)
- 开源项目 (4)
- 多线程 (2)
- Console App (6)
- 个人开源项目 (4)
- IBM DevelopWorks (4)
- Java (16)
- 内存泄漏相关调试和检测 (13)
- 软件测试相关技术 (2)
- C# (11)
- Apple Related (1)
- 软件测试和管理 (2)
- EMV (1)
- Python (1)
- Node.js (6)
- JavaScript (5)
- VUE (1)
- Frontend (1)
- Backend (4)
- RESTful API (3)
- Firebase (3)
最新评论
-
u013189503:
来个密码吧
[C++][Logging] 项目中写日志模块的实现 -
wyf_vc:
来个密码啊!!
[C++][Logging] 项目中写日志模块的实现
转自:http://hi.baidu.com/liudeandg/blog/item/121633ddd2bf71265882dd20.html
位域 :
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:
struct bs
{
int a:8;
int b:2;
int c:6;
}data;
说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:
1. 一个位域必须存储在同一个字节中,不能跨两个字节(这个限制好像仅限于char型)。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*从下一单元开始存放*/
unsigned c:4
}
在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。
3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /*该2位不能使用*/
int b:3
int c:2
};
从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。
二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名•位域名 位域允许用各种格式输出。
main(){
struct bs
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
bit.a=1;
bit.b=7; //注意:位域的赋值不能超过该域所能表示的最大值,如b只有3位,能表示的最大数为7,若赋为8,就会出错
bit.c=15;
printf("%d,%d,%d\n",bit.a,bit.b,bit.c);
pbit=&bit;
pbit->a=0;
pbit->b&=3;
pbit->c=1;
printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);
}
上例程序中定义了位域结构bs,三个位域为a,b,c。说明了bs类型的变量bit和指向bs类型的指针变量pbit。这表示位域也是可以使用指针的。
程序的9、10、11三行分别给三个位域赋值。( 应注重赋值不能超过该位域的答应范围)程序第12行以整型量格式输出三个域的内容。第13行把位域变量bit的地址送给指针变量pbit。第14行用指针 方式给位域a重新赋值,赋为0。第15行使用了复合的位运算符"&=", 该行相当于: pbit->b=pbit->b&3位域b中原有值为7,与3作按位与运算的结果为3(111&011=011,十进制值为 3)。同样,程序第16行中使用了复合位运算"=", 相当于: pbit->c=pbit->c1其结果为15。程序第17行用指针方式输出了这三个域的值。
我们再来看看下面两个结构体定义:
struct foo2 {
char a : 2;
char b : 3;
char c : 1;
};
struct foo3 {
char a : 2;
char b : 3;
char c : 7;
};
我们来打印一下这两个结构体的大小,我们得到的结果是:
sizeof(struct foo2) = 1
sizeof(struct foo3) = 2
显然都不是我们期望的,如果按照正常的内存对齐规则, 这两个结构体大小均应该为3才对,那么问题出在哪了呢?首先通过这种现象我们可以肯定的是:带有'位域'的结构体并不是按照每个域对齐的,而是将一些位域 成员'捆绑'在一起做对齐的。以foo2为例,这个结构体中所有的成员都是char型的,而且三个位域占用的总空间为6 bit < 8 bit(1 byte),这时编译器会将这三个成员'捆绑'在一起做对齐,并且以最小空间作代价,这就是为什么我们得到sizeof(struct foo2) = 1这样的结果的原因了。再看看foo3这个结构体,同foo2一样,三个成员类型也都是char型,但是三个成员位域所占空间之和为9 bit > 8 bit(1 byte),这里位域是不能跨越两个成员基本类型空间的,这时编译器将a和b两个成员'捆绑'按照char做对齐,而c单独拿出来以char类型做对齐, 这样实际上在b和c之间出现了空隙,但这也是最节省空间的方法了。我们再看一种结构体定义:
struct foo4 {
char a : 2;
char b : 3;
int c : 1;
};
在foo4中虽然三个位域所占用空间之和为6 bit < 8 bit(1 byte),但是由于char和int的对齐系数是不同的,是不能捆绑在一起,那是不是a、b捆绑在一起按照char对齐,c单独按照int对齐呢?我们 打印一下sizeof(struct foo4)发现结果为8,也就是说编译器把a、b、c一起捆绑起来并以int做对齐了。就是说不够一个类型的size时,将按其中最大的那个类型对齐。此 处按int对齐。
网上有如下的解释:
/*************************************************************************
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,
允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
段将从新的存储单元开始,其偏移量为其类型大小的整数倍;(经测试此条好像仅限于char型,整型可以跨域存储)
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
***************************************************************************/
struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};
struct s2
{
int i: 8;
int j: 4;
double b;
int a:3;
};
printf("sizeof(s1)= %d\n", sizeof(s1));
printf("sizeof(s2)= %d\n", sizeof(s2));
result: 16, 24
第一个结构体中,i,j,a共占15个位,不足8个字节,按double 8字节对齐,共16字节
第二个结构体中,i,j共占12位,不足8字节,按8字节对齐,a也按8字节对齐,加上double共8+8+8=24个字节
位域的定义如下 :
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
位域有几点说明:
1、一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始,比如利用空域和无位域名的位域。
2、位域的长度不能大于数据类型本身的长度,比如int类型就能超过32位二进位。有其他人说是不能超过8位,我在我的机子上(linux as4系统)是可以实现int :32的位域长度的。莫非是位域重新进行定义了?
3、位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。
二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名·位域名
位域允许用各种格式输出。
举个例子:
1 #include <stdio.h>
2
3 int main()
4 {
5 struct bs
6 {
7 char a:1;
8 char b:3;
9 char :0; /*空域*/
10 char c:4;
11 char :6; /*无位域名的位域*/
12 int e:18;
13 } __attribute__((packed)); /*必须增加__attribute__((packed)),否则对齐的时候会和预计结果不同*/
14
15 struct bs bit,*pbit;
16
17 printf("size of char is %d\n", sizeof(char));
18 printf("size of int is %d\n", sizeof(int));
19
20 printf("size of bit is %d\n", sizeof(bit));
21
22 return 0;
23 }
运行的结果1如下:
size of char is 1
size of int is 4
size of bit is 4
如果把程序第12行的e:18改为19的话,那么运行结果2如下:
size of char is 1
size of int is 4
size of bit is 5
如果把程序第13行的__attribute__((packed))去掉,那么运行结果3如下:
size of char is 1
size of int is 4
size of bit is 8
对运行结果123进行比较可以得知:
1、位域长度可以大于8,具体看数据类型,我测试了每一种数据类型,每一种类型的最大位域长度均为自身类型的长度;
2、空域的作用在添加了__attribute__((packed))之后失效;
3、未添加__attribute__((packed))的位域会对数据进行对齐:
例如:
{
char a:5;
int b:27;
};
bf的字节数为4,如果将a的位域改为6,那么a和b的位域长度和超过int的长度32,int类型根据自身长度的倍数进行对齐,所以bf的字节数则变为8。
同样
{
int b:27;
char a:5;
}
也有同样的结论。
如果添加了了__attribute__((packed)),那么系统会对数据进行压缩,而不会发生bf的结果。
发表评论
-
FreeRTOS
2022-03-05 16:31 248Ref https://blog.csdn.net/weix ... -
串口通讯相关
2018-11-02 13:44 411https://bbs.csdn.net/wap/topics ... -
[转]C++验证IP是否可以PING通
2018-10-30 17:54 1325https://www.cnblogs.com/guoyz13 ... -
C++/MFC 換皮膚
2018-10-20 11:05 477https://blog.csdn.net/u01123991 ... -
WinCE 截屏 - C++ 代碼
2018-08-31 09:45 574// this function create a bmp ... -
Android NDK搭建環境
2017-11-27 13:25 580https://www.cnblogs.com/ut2016- ... -
8583协议相关
2017-10-17 13:38 5738583相关资料,整理中... -
Java高级应用之JNI
2017-06-19 09:00 600参考link http://www.cnblogs.com/l ... -
C++实现ping功能
2017-04-18 11:21 2155基础知识 ping的过程是向目的IP发送一个type=8的I ... -
OpenSSL 编译环境搭建
2017-03-27 15:01 9061 安裝VS2008到 c:\Program Files (x ... -
最优非对称加密填充(OAEP)
2017-03-25 14:53 1582OpenSSL命令---rsautl http://blog. ... -
[Platform Builder] 设置SVM OS build Env
2016-11-10 11:39 01 copy one OSDesign Project to ... -
[Windows] System Error Codes(GetLastError )0-----5999
2016-10-26 13:28 1881ERROR_SUCCESS 0 (0x0) T ... -
开源Windows驱动程序框架
2016-09-17 21:35 871转自 http://code.csdn.net/news/28 ... -
c/c++代码中执行cmd命令
2016-09-14 14:50 1908转自 http://blog.csdn.net/slixinx ... -
C#使用C++标准DLL实例(包含callback)
2016-09-11 19:44 1086C++编写标准Win32DLL如下 头文件 /***** ... -
C#调用C++的DLL搜集整理的所有数据类型转换方式
2016-09-09 16:07 969转自 http://www.cnblogs.com/zeroo ... -
WinCE CPU使用率计算 测试工具
2016-09-08 16:14 991转自 http://blog.csdn.net/jan ... -
switch在C++与C#中的一些差异
2016-09-08 15:19 810参考链接 http://blog.csdn.net/weiwe ... -
C++ 鼠标模拟程序
2016-09-04 12:09 1612转自 http://blog.csdn.net/weixinh ...
相关推荐
"C/C++位域详细介绍" C/C++中的位域(Bit Field)是指在结构体中使用的位域成员,它们可以将整数成员存储到比编译器通常允许的更小的内存空间中。位域的宽度可以通过常量整数表达式来指明。这种技术广泛应用于需要...
总结来说,C++的位域是一种高级的数据结构,它允许程序员精确控制内存的使用,提高代码效率。然而,由于编译器实现的差异,位域在跨平台编程时可能存在兼容性问题,因此在使用位域时需谨慎,特别是在编写需要移植的...
位域(Bit-fields)是 C 语言和 C++ 语言中都有的一个概念,但是位域有很多需要注意的问题。其中一个重要的问题是大端和小端字节序的问题。 大端和小端字节序是计算机科学中的一种约定,用于描述多字节数字在计算机...
12.2 位域(位段) 194 12.3 本章小结 13 文件 13.1 C文件概述 197 13.2 文件指针 198 13.3 文件的打开与关闭 199 13.3.1 文件的打开(fopen 函数) 200 13.3.2 文件关闭函数(fclose函数) 202 13.4 文件的读写 204 ...
12.2 位域(位段) 194 12.3 本章小结 13 文件 13.1 C文件概述 197 13.2 文件指针 198 13.3 文件的打开与关闭 199 13.3.1 文件的打开(fopen 函数) 200 13.3.2 文件关闭函数(fclose函数) 202 13.4 文件的读写 204 ...
位域是将一个字节的二进制位划分为多个独立的区域,每个区域有自己的位数。这在需要节省存储空间的情况下非常有用。定义位域结构如下: ```cpp struct Flags { unsigned isSet : 1; // 1位的位域,表示一个布尔状态...
数组是 C++ 语言中的一种数据结构,用于存储一组相同类型的数据。字符串是 C++ 语言中的一种数据类型,用于存储字符序列。函数指针是 C++ 语言中的一种数据类型,用于存储函数的地址。类和对象是 C++ 语言中的一种...
在C++中,`extern "C"`是一个关键字,用于告诉编译器按照C语言的规则来处理声明或定义,而不是C++的规则。这在使用C库函数或在C++代码中调用C代码时特别有用,因为它避免了C++的名称修饰(name mangling),确保了...
### 嵌入式C/C++语言精华文章集锦概览 #### 1. C/C++语言struct深层探索 在嵌入式系统编程中,`struct`是非常重要的数据组织工具,它允许程序员定义复杂的复合数据类型,从而更方便地管理和传递数据。在本章节中,...
### C/C++ 笔试题详解 #### 1. `volatile` 是什么? `volatile` 是一个关键字,在 C/C++ 中用来修饰变量。当一个变量被声明为 `volatile` 类型时,编译器不会对它进行优化(例如,将它保存在寄存器中而不是内存中...
位域是C++中一种节省存储空间的机制,允许结构体或类的成员占用比整型类型更少的位。位域声明的语法是`declarator : constant-expression`,其中`declarator`是成员的名称,`constant-expression`指定了成员占用的...
在嵌入式系统编程领域,C和C++是两种常用且强大的编程语言。它们的高效性、灵活性和底层控制能力使得它们成为构建嵌入式软件的理想选择。以下是一些关于C和C++嵌入式系统编程的重要知识点: 1. **内存管理**: - *...
位域(Bit Fields),也被称为位段,是C/C++中的一种特殊的数据结构,它允许在一个整数类型(通常是`unsigned int`)中定义一系列具有固定宽度的字段,每个字段占据一个或多个位。这种特性非常适用于硬件接口编程和...
在软件层面,高级编程语言如C和C++也提供了位字段(bit-field)结构,允许程序员定义结构体中的变量为固定宽度的位。 位域操作在电子政务领域也有广泛应用,比如在智能卡、身份认证和数据安全等方面。通过位域操作...
2. **结构化语言**:C语言支持结构化编程,允许使用条件语句、循环、函数等结构化编程概念。 3. **内存管理**:C语言提供了对内存的直接控制,包括动态内存分配和手动内存管理。 4. **可移植性**:C语言编写的程序...
此外,C#的`long`类型是64位,而C++中的`long`通常是32位。 C#的`struct`是值类型,与C++的`class`(引用类型)在语义上有本质区别。值类型在赋值或作为参数传递时会复制整个对象,而引用类型仅复制对对象的引用。 ...
位域结构方法利用C++的struct和bits-field特性,定义外设寄存器结构,简化对寄存器的操作。在使用Bits-Fields编程时,需要考虑Read-Modify-Write(RMW)问题和代码大小的影响。 4. **外设范例** 示例代码通常包括...
### C281x C/C++ Header Files and Peripheral Examples #### 一、设备支持与介绍 本软件包支持包括但不限于以下几种281x系列器件:TMS320F2812、TMS320F2811、TMS320F2810、TMS320C2812、TMS320C2811、TMS320C...