共用体union详解

一共用体的概念

当需要把不同类型的变量存放到同一段内存单元或对同一段内存单元的数据按不同类型处理则

需要使用共用体数据结构

例把一个整型变量一个字符型变量一个实型变量放在同一个地址开始的内存单元中

共用体的定义形式

union 共用体名

成员列表

变量列表

注意区分

共用体各成员占相同的起始地址所占内存长度等于最长的成员所占内存

结构体各成员占不同的地址所占内存长度等于全部成员所占内存之和

二共用体变量的引用

只能引用共用体变量的成员如

union data a;

a.i;

a.ch;

a.f;

三共用体类型数据的特点

共用体变量中的值是最后一次存放的成员的值如

a.i = 1;

a.ch = ‘a‘;

a.f = 1.5;

完成以上三个赋值语句后共用体边量的值是 1.5而 a.i=1 和 a.ch=‘a‘已无意义

共用体变量不能初始化例

union data

{

int i;

char ch;

float f;

}a={1,‘a‘, 1.5}  错误!!!

共用体常用来节省内存,特别是一些嵌入式编程,内存是非常宝贵的!

共用体也常用于操作系统数据结构或硬件数据结构!

union在操作系统底层的代码中用的比较多,因为它在内存共赏布局上方便且直观。所以网络编程,协议分析,内核代码上有一些用到union都比较好懂,简化了设计。

妙用实例

1. 为了方便看懂代码。

比如说想写一个3 * 3的矩阵,可以这样写:

[ 注:下面用红色部分标记的地方是后来添加上去的,谢谢yrqing718的提醒!]

  1. struct  Matrix
  2. {
  3. union
  4. {
  5. struct
  6. {
  7. float  _f11, _f12, _f13, _f21, _f22, _f23, _f31, _f32, _f33;
  8. };
  9. float  f[3][3];
  10. }_matrix;
  11. };
  12. struct  Matrix m;

这两个东西共同使用相同的空间,所以没有空间浪费,在需要整体用矩阵的时候可以用

m._matrix.f (比如说传参,或者是整体赋值等);需要用其中的几个元素的时候可以用m._matrix._f11那样可以避免用m.f[0][0](这样不大直观,而且容易出错)。

2. 用在强制类型转换上(比强制类型转换更加容易看懂)

下面举几个例子:

(1). 判断系统用的是big endian 还是 little endian(其定义大家可以到网上查相关资料,此略)

  1. #define TRUE 1
  2. #define FALSE 0
  3. #define BOOL int
  4. BOOL  isBigEndian()
  5. {
  6. int  i = 1;   /* i = 0x00000001*/
  7. char  c = *(char  *)&i; /* 注意不能写成 char c = (char)i; */
  8. return  (int )c
    != i;
  9. }

如果是little endian字节序的话,那个i = 1;的内存从小到大依次放的是:0x01
0x00 0x00 0x00,如是,按照i的起始地址变成按照char *方式(1字节)存取,即得c
= 0x01;

反之亦然

也许看起来不是很清晰,下面来看一下这个:

  1. BOOL  isBigEndian()
  2. {
  3. union
  4. {
  5. int  i;
  6. char  c;
  7. }test;
  8. test.c = 2;
  9. return  test.i != 2;
  10. }

这里用的是union来控制这个共享布局,有个知识点就是union里面的成员c和i都是从低地址开始对齐的。同样可以得到如此结果,而且不用转换,清晰一些。

什么,不觉得清晰??那再看下面的例子:

(2).将little endian下的long
long类型的值换成 big endian类型的值。已经知道系统提供了下面的api:long
htonl(long lg);作用是把所有的字节序换成大端字节序。因此得出下面做法:

  1. long  long  htonLL(long  long  lg)
  2. {
  3. union
  4. {
  5. struct
  6. {
  7. long  low;
  8. long  high;
  9. }val_1;
  10. long  long  val_2;
  11. }val_arg, val_ret;
  12. if ( isBigEndian() )
  13. return  lg;
  14. val_arg.val_2 = lg;
  15. val_ret.val_1.low = htonl( val_arg.val_1.high );
  16. val_ret.val_1.high = htonl( val_arg.val_1.low );
  17. return  val_ret.val_2;
  18. }

只要把内存结构的草图画出来就比较容易明白了。

(3).为了理解c++类的布局,再看下面一个例子。有如下类:

  1. class  Test
  2. {
  3. public :
  4. float  getFVal(){ return  f;}
  5. private :
  6. int  i;
  7. char  c;
  8. float  f;
  9. };
  10. Test t;

不能在类Test中增加代码,给对象中的f赋值7.0f.

  1. class  Test_Cpy
  2. {
  3. public :
  4. float  getVal(){ return  f;}
  5. float  setVal(float  f){ this ->f = f;}
  6. private :
  7. int  i;
  8. char  c;
  9. float  f;
  10. };
  11. ....
  12. int  main()
  13. {
  14. Test t;
  15. union
  16. {
  17. Test t1,
  18. Test_Cpy t2;
  19. }test;
  20. test.t2.setVal(7.0f);
  21. t = test.t1;
  22. assert( t.getVal() == 7.0f );
  23. return  0;
  24. }

说明:因为在增加类的成员函数时候,那个类的对象的布局基本不变。因此可以写一个与Test类一样结构的类Test_Cpy,而多了一个成员函数setVal,再用uinon结构对齐,就可以给私有变量赋值了。(这种方法在有虚机类和虚函数机制时可能失灵,故不可移植)至于详细的讨论,网上有,这个例子在实际中没有用途,只是用来考察这个内存布局的使用而已.

4

  1. 在嵌入式系统开发中,有时需要将一些变量存储在EEPROM中,变量类型若是char、int就很好办,可是如果要存储float、double类型的变量怎么办呢?

    这个问题可以用共用体解决:

    union myfloat

    {

        char i[4];

        float j;

    }Test;

    因为float是四个字节,因此我们定义一个4个元素的char数组和float公用一段内存,接下来就是EEPROM存取了

  2. 2

    在程序中要使用 j 的地方使用Test.j就行了,

    想把 j 存入EEPROM可以这样:

    EEPROM_WRITE(0,myfloat.i[0]);

    EEPROM_WRITE(1,myfloat.i[1]);

    EEPROM_WRITE(2,myfloat.i[2]);

    EEPROM_WRITE(3,myfloat.i[3]);

    注:上面参数0、1、2、3为EEPROM地址,上面的EEPROM_WRITE只是示意,有时需要对地址使用(void*)进行类型转换

  3. 3

    想把 j 从EEPROM读出可以这样:

    myfloat.i[0]=EEPROM_READ(0);

    myfloat.i[1]=EEPROM_READ(1);

    myfloat.i[2]=EEPROM_READ(2);

    myfloat.i[3]=EEPROM_READ(3);

    然后在程序中继续使用Test.j就可以了

    是不是很简单呢

共用体union详解

时间: 2024-10-25 08:42:18

共用体union详解的相关文章

结构体对齐详解【转】

 1 -- 结构体数据成员对齐的意义 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus).这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度.比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个

mysql union 详解

Union:作用:把2次或多次查询结果合并起来要求:两次查询的列数一致推荐:查询的每一列,相对应的列类型也一样 可以来自于多张表 多次sql语句取出的列名可以不一致,此时,以第1个sql的列名为准 例一. select user_name,user_email,msg_content from ecs_feedback where msg_status = 1 union select user_name,email,content from ecs_comment where status =

(C语言)共用体union的使用方法举例

曾经在学校学习C语言的时候一直搞不懂那个共用体union有什么用的.工作之后才发现它的一些妙用,现举比例如以下: 1. 为了方便看懂代码. 比方说想写一个3 * 3的矩阵,能够这样写: [ 注:以下用红色部分标记的地方是后来加入上去的,谢谢yrqing718的提醒!] struct  Matrix { union { struct { float  _f11, _f12, _f13, _f21, _f22, _f23, _f31, _f32, _f33; }; float  f[3][3]; }

共用体union

目录 ????- 概述 ????????- 基本语法 ????????- 匿名共用体 ????- 改进 ?? 概述 结构体struct可以同时存储int.long.double等不同类型, 而共用体union只能存储int.long.double等不同类型中的一个. 共用体union比struct节省内存,常用于配置低的硬件,如控制烤箱.MP3播放器或火星漫步者等嵌入式編程. 基本语法 union one4all { ????int int_val; ????long long_val; ???

共用体(union)

在C语言中,当不同数据类型的数据共同占有使用一块内存空间时,这个数据构造类型叫做共用体,也叫联合体.共用体用的地方比较少,使用形式与结构体类似,但是内存使用方式不同. 1--- 定义 union 共用体类型名 { 成员表列: }变量名1:union 共用体类型名 变量名2: 2--- 成员共用同一个存储区域,共用体类型变量是以最后一次

C语言共用体union

union共用体说明: 当一个共用体被声明时, 编译程序自动地产生一个变量, 其长度为联合中最大的变量长度的整数倍. 比如union中有{int x; double x1; char name[10];}这个共用体的长度为10字节,因为name[10]是这个共用体中最大的一个变量 #include <stdio.h> struct A { int num; char name[20]; char job; union //共用体关键字union { int x; char zy[20]; }t

C结构体struct 和 共用体union的使用测试

#include <stdio.h> struct { char name[10]; char sex; char job; int num; union{ //联合只能共用同一个内存 int class; char position[10]; }category; }PE[2]; int main(){ int i; for(i=0;i<2;i++){ printf("请输入:号码 姓名 性别 职业\n"); scanf("%d %s %c %c"

go语言之行--结构体(struct)详解、链表

一.struct简介 go语言中没有像类的概念,但是可以通过结构体struct实现oop(面向对象编程).struct的成员(也叫属性或字段)可以是任何类型,如普通类型.复合类型.函数.map.interface.struct等,所以我们可以理解为go语言中的“类”. 二.struct详解 struct定义 在定义struct成员时候区分大小写,若首字母大写则该成员为公有成员(对外可见),否则是私有成员(对外不可见). type struct_variable_type struct { mem

C语言结构体指针详解

结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针. 指向结构体变量的指针 前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针. 前面讲过,&student1 表示结构体变量 student1 的首地址,即 student1 第一个项的地址.如果定义一个指针变量 p 指向这个地址的话,p 就可以指向结构体变量 student1 中的任意一个成员. 那么,这个指针变量定义成什么类型呢?只能定义成结构体类型,且指向什么结构体类型的结构体变量,