C语言中的联合体
C语言中的联合体
联合体是C语言中的一个比较好玩的语法,是一个共享内存的一种数据结构,在一些特殊的场合下特别有优势,下面就对联合体做一个简单的介绍。
联合体类型转换
问题:如何实现string
类型的到浮点类型的转换?比如一个[0x12, 0x34, 0x56, 0x78]的char
型到浮点float
型。
实现思路:这个如果用传统的换算方式做会非常复杂,涉及到float类型的存储格式,当然万能的C语言还可以用指针来搞定,一个简单的实现方式是采用联合体union
来实现,这个是一个非常典型的共享内存的问题,而union
正是为了共享内存设置的。
代码实现
#include "stdio.h"
typedef union _temp_t {
char s[4]; // char 类型的写入读取方式,1 float = 4 char
float temp; // float 类型的写入读取方式
}temp_t;
int main(){
temp_t value;
value.s[0] = 0x12;
value.s[1] = 0x34;
value.s[2] = 0x56;
value.s[3] = 0x78;
printf("Float value is %g\n", value.temp);
value.temp = 12.3456;
printf("char value is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
value.s[0], value.s[1], value.s[2], value.s[3]
);
}
输出
Float value is 1.73782e+34
char value is 0x94, 0x87, 0x45, 0x41
结构体位域
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
- 一个位域必须存储在同一个单元中,不能跨两个单元。如一个单元所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs
{
unsigned int a:4
unsigned int :0
unsigned int b:4
unsigned int c:4
}
这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
- 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct k
{
int a:1
int :2
int b:3
int c:2
};
位域操作在一些状态位的读取和写入时特别有用,比如下面的一个定义:
typedef union _sdcard_csd {
unsigned int csd[4];
struct {
// csd[0]
unsigned int :2;
unsigned int file_format :2;
unsigned int temp_write_protect :1;
unsigned int prem_write_protect :1;
unsigned int copy :1;
unsigned int file_format_gpr :1;
unsigned int :5;
unsigned int write_bl_partial :1;
unsigned int write_bl_len :4;
unsigned int r2w_factor :3;
unsigned int :2;
unsigned int wp_grp_enable :1;
unsigned int wp_grp_size :7;
unsigned int sector_size_1 :1;
// csd[1]
unsigned int sector_size_2 :6; // 不能跨单元,所以只有分成两个。
unsigned int erase_blk_en :1;
unsigned int :1;
unsigned int c_size :22;
unsigned int :2;
// csd[2]
unsigned int :4;
unsigned int dsr_imp :1;
unsigned int read_blk_misalign :1;
unsigned int write_blk_misalign :1;
unsigned int read_bl_partial :1;
unsigned int read_bl_len :4;
unsigned int ccc :12;
unsigned int tran_speed :8;
// csd[3]
unsigned int nsac :8;
unsigned int taac :8;
unsigned int :6;
unsigned int csd_struct :2;
unsigned int :8;
};
} sdcard_csd;
上述代码就实现了一个128bit到各种状态的一个映射。
最后更新于 2017-07-31 08:48:27 并被添加「」标签,已有 2427 位童鞋阅读过。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。