c99 位域问题

http://www.cnblogs.com/my_life/articles/2293397.html


位域成员不能单独被取sizeof值(编译报错),我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其它类型类型的存在。使用位域的主要目的是压缩存储,其大致规则为:

1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。

 

和结构体一样,位结构体也是按照成员的最大长度字节来对齐分配空间的。


测试:
struct test
 {
  char a:1;
  char :2;
  long b:3;
  char c:2;
 };
 test t1;
 int len=sizeof(t1);   //len=12,前两个位域共用一个char空间,按第三个位域long扩展为4字节空间,最后一个位域占用一个char空间,按最长位域空间扩展为4字节。

 

struct test
{
char f1 : 3;
short f2 : 4;
char f3 : 5;
};
test t1;
int len=sizeof(t1); //len=6,第一位域占用一个char空间,按第二个位域short扩展为2字节空间,最后一个位域占用一个char空间,按最长位域空间扩展为2字节。

 

如果位域上的整形范围值是0,则下个位域从新的字节开始,前一字段后面空出的所有字节都不使用(即使是同类型的位域),如:

struct bs
{
    unsigned a:4;
    unsigned :0;      // 空域
    unsigned b:4;    // 从新字节开始存放
    unsigned c:4;
} ;

sizeof(unsigned) == 4

上面这个位域定义中,a占第一字节的4位,第一个字节的后4位以及后面的3个字节都填0表示不使用,b从新的字节开始,占用4位,c占用4位。上面位结构体大小为:8


struct test
 {
  char a:1;
  char :2;
  char b:3;
  long c:2;
 };
 test t1;
 int len=sizeof(t1);   //len=8

struct test
 {
  char a:1;
  char :2;
  char b:3;
  char c:2;
 };
 test t1;
 int len=sizeof(t1);   //len=1


<think>我们正在处理用户关于C语言结构体的问题。根据用户要求,我们需要提供清晰的结构化回答,并生成相关问题。 同时,我们需要遵循系统级指令,包括使用正确的LaTeX格式(行内公式用$...$,独立公式用$$...$$),使用中文回答,并在引用的段落末尾添加引用标识。 用户问题:我想了解结构体的定义和使用 请问C语言 结构体 定义 使用方法 根据之前提供的参考引用[1](关于C语言结构体定义详解与实例),我们知道允许在结构体中以为单指定成员所占内存长度,用于节省内存,常用于嵌入式、网络协议等。 回答结构: 1. 结构体的定义:解释如何定义结构体,语法规则。 2. 结构体的使用:如何声明变量、访问成员,以及注意事项。 3. 示例代码:展示定义和使用结构体的代码。 4. 应用场景:简要说明的使用场景。 5. 注意事项:使用时可能遇到的问题和限制。 注意:由于用户的问题集中在定义和使用方法,我们将重点放在这两部分。 同时,我们需要在回答末尾生成相关问题。 开始回答:</think>### C语言结构体详解 (bit field)是C语言中一种特殊的结构体成员,允许以为单指定成员所占内存长度,用于高效利用存储空间[^1]。 #### 一、结构体定义 语法格式: ```c struct 结构体名 { 数据类型 成员名 : 宽; }; ``` - **宽**:指定成员占用的二进制数(1~32) - **数据类型**:只能是`int`、`unsigned int`或`signed int`(C99标准支持`_Bool`) 示例定义: ```c struct BitField { unsigned int flag : 1; // 1标志 unsigned int mode : 3; // 3模式值 unsigned int : 4; // 4无名填充 signed int value : 8; // 8有符号值 }; ``` #### 二、使用方式 1. **成员访问**:与普通结构体相同 ```c struct BitField bf; bf.flag = 1; // 赋值(仅存储0/1) bf.mode = 5; // 3最大存储7 (2³-1) ``` 2. **跨字节存储规则**: - 成员不可跨字节边界(自动对齐) - 示例:`unsigned a:6, b:4;` 将占用2字节(6+4>8) 3. **无名**: ```c struct { unsigned a : 4; unsigned : 2; // 无名填充 unsigned b : 2; }; ``` #### 三、完整使用示例 ```c #include <stdio.h> // 定义网络协议头部 struct IPHeader { unsigned int version : 4; // 版本号 unsigned int ihl : 4; // 头部长度 unsigned int tos : 8; // 服务类型 unsigned int total_length : 16; // 总长度 }; int main() { struct IPHeader header = {4, 5, 0, 1500}; printf("版本: %u\n", header.version); printf("头部长度: %u 字\n", header.ihl); printf("总长度: %u 字节\n", header.total_length); // 内存占用验证 printf("结构体大小: %zu 字节\n", sizeof(header)); // 输出4字节 return 0; } ``` #### 四、典型应用场景 1. **嵌入式系统**:寄存器映射(如`STM32`的寄存器定义) 2. **网络协议**:TCP/IP头部字段封装 3. **硬件交互**:设备控制寄存器操作 4. **状态压缩**:多个布尔标志组合存储 #### 五、注意事项 1. **取地址操作**:`&`不能用于成员(因小于1字节) 2. **跨平台兼容性**:的内存布局取决于编译器实现 3. **溢出风险**:赋值超过宽时发生截断(如3字段赋值8会得到0) 4. **字节序问题**:大端/小端架构影响排列顺序 > 通过精准控制内存布局,在资源受限场景(如嵌入式开发)中可显著降低内存占用[^1]。实际开发需结合编译器文档验证内存布局。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值