C 语言位域:高效内存使用的实战技巧
假设 C 程序包含若干 TRUE/FALSE 变量,归组在结构体 status 中:
struct { unsigned int widthValidated; unsigned int heightValidated; } status;
此结构需 8 字节内存,但实际每变量只存 0 或 1。C 语言提供更好方式利用内存。
若在结构体内使用此类变量,可定义变量宽度,告诉编译器仅使用指定位数。上例可重写为:
struct { unsigned int widthValidated : 1; unsigned int heightValidated : 1; } status;
上结构 status 变量需 4 字节内存,但仅用 2 位存值。
若用 32 个变量每个宽 1 位,status 仍用 4 字节。但一旦有 33 个变量,将分配下一内存槽,开始用 8 字节。下例验证概念:
Live Demo
#include <stdio.h> #include <string.h> /* define simple structure */ struct { unsigned int widthValidated; unsigned int heightValidated; } status1; /* define a structure with bit fields */ struct { unsigned int widthValidated : 1; unsigned int heightValidated : 1; } status2; int main( ) { printf( "Memory size occupied by status1 : %d\n", sizeof(status1)); printf( "Memory size occupied by status2 : %d\n", sizeof(status2)); return 0; }
编译执行输出:
Memory size occupied by status1 : 8 Memory size occupied by status2 : 4
位域声明
结构体内位域声明形式:
struct { type [member_name] : width ; };
下表描述位域变量元素:
| 序号 | 元素及说明 |
|---|---|
| 1 | type 决定位域值如何解释的整数类型。类型可为 int、signed int 或 unsigned int。 |
| 2 | member_name 位域名称。 |
| 3 | width 位域位数。宽度必须小于或等于指定类型的位宽。 |
带预定义宽度的变量称为位域。位域可容纳多位;例如需存 0 到 7 的值,可定义宽度 3 位的位域:
struct { unsigned int age : 3; } Age;
上定义指示编译器 age 变量仅用 3 位存值。若尝试用超 3 位值则不允许。测试示例:
Live Demo
#include <stdio.h> #include <string.h> struct { unsigned int age : 3; } Age; int main( ) { Age.age = 4; printf( "Sizeof( Age ) : %d\n", sizeof(Age) ); printf( "Age.age : %d\n", Age.age ); Age.age = 7; printf( "Age.age : %d\n", Age.age ); Age.age = 8; printf( "Age.age : %d\n", Age.age ); return 0; }
编译会警告,执行输出:
Sizeof( Age ) : 4 Age.age : 4 Age.age : 7 Age.age : 0
C语言
- 掌握 C# 位运算与移位运算符:全面指南
- C 语言用户自定义函数四大模式对比:参数与返回值的设计权衡
- C语言中将一维与二维数组传递给函数的实战指南
- 精通C语言结构体与指针:实战指南
- C++ 结构体详解:定义、初始化、指针、函数参数与局限性
- C 语言函数详解:定义、声明、调用与参数传递
- C 语言可变参数详解:stdarg.h 实战指南
- C# 方法完全指南:定义、调用、递归与参数传递
- 深入理解 C# 委托:函数引用与事件的完整指南
- MATLAB 积分完全指南:不定/定积分、面积计算与符号/数值方法
- Java StringBuilder 与 StringBuffer:高性能字符串操作
- 精通 Java 封装:数据隐藏实战指南