曾经在学校学习C语言的时候一直搞不懂那个共用体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](这样不大直观,并且easy出错)。

2. 用在强制类型转换上(比强制类型转换更加easy看懂)
以下举几个样例:

(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. }

仅仅要把内存结构的草图画出来就比較easy明确了。

(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结构对齐,就能够给私有变量赋值了。(这样的方法在有虚机类和虚函数机制时可能失灵,故不可移植)至于具体的讨论,网上有,这个样例在实际中没实用途,仅仅是用来考察这个内存布局的使用而已.

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

(C语言)共用体union的使用方法举例的更多相关文章

  1. C语言共用体union

    union共用体说明: 当一个共用体被声明时, 编译程序自动地产生一个变量, 其长度为联合中最大的变量长度的整数倍. 比如union中有{int x; double x1; char name[10] ...

  2. C语言共用体、大小端、枚举

    1.共用体和结构体的相同和不同 (1)相同点就是操作语法几乎相同.(2)不同点是本质上的不同.struct是多个独立元素(内存空间)打包在一起:union是一个元素(内存空间)的多种不同解析方式. # ...

  3. C语言 共用体

    //共用体 union #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #includ ...

  4. C语言共用体(Union)

    通过前面的讲解,我们知道结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员.在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union),它的定义格式为: uni ...

  5. 共用体union

    union共用体名 { 类型名 成员名1: 类型名 成员名2: …… 类型名 成员名n; } 由于各个成员变量在内存中都使用同一段存储空间,因此共用体变量的长度等于最长的成员长度,共用体的访问方式和结 ...

  6. 共用体 union

    共用体是一种数据格式,能够存储不同的数据类型,但只能同时存储其中的一种类型. union one4all { int int_val; double double_val; long long_val ...

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

    #include <stdio.h> struct { char name[10]; char sex; char job; int num; union{ //联合只能共用同一个内存 i ...

  8. 以位为单位存储标志-共用体-union

    一.程序的结构如下: typedef union _KEYST     {         struct         {             uint8 Key1_Flag :1;//表示第0 ...

  9. C语言联合体(union)的使用方法及其本质-union

    转载自:https://blog.csdn.net/si_zhou_qun_84342712/article/details/53187106 1.联合体union的基本特性——和struct的同与不 ...

随机推荐

  1. JS学习笔记-OO创建怀疑的对象

    问了.工厂介绍,解决重码 前面已经提到,JS中创建对象的方法.不难发现,主要的创建方法中,创建一个对象还算简单,假设创建多个类似的对象的话就会产生大量反复的代码. 解决:工厂模式方法(加入一个专门创建 ...

  2. WebStorm的compass配置

    在webstorm中配置compass WebStorm是功能强大的前端开发专用IDE,拥有即时编辑(chrome).自动完成.debugger.Emmet.HTML5 支持.JSLint.Less. ...

  3. Cordova WP8 平台安装部署

    原文:Cordova WP8 平台安装部署 Cordova是一个开放源码移动开发框架. 它允许您使用标准的 web 技术如 HTML5. CSS3 和 JavaScript 进行跨平台开发,避免每个移 ...

  4. SPOJ 15. The Shortest Path 堆优化Dijsktra

    You are given a list of cities. Each direct connection between two cities has its transportation cos ...

  5. WPF学习(4)逻辑树和可视树

    前面几节说了一些WPF的基础,包括XAML和布局等.在接下来的几节,我们来说说WPF的核心概念,包括逻辑树和可视树.依赖对象和依赖属性.路由事件.命令这几个部分.本节介绍下逻辑树(Logical Tr ...

  6. Windows命令行命令集锦

    原文:Windows命令行命令集锦 转自:http://www.me2wg.com/bbs/forum.php?mod=viewthread&tid=15830 winver--------- ...

  7. “NET网络”进行中,多管齐下的人才力挫“”粗俗

            随着互联网的迅猛发展,一些不太干净.低俗的甚至色情的内容不断浮现.不仅严重影响了我们的上网体验,也成为扰乱互联网正常秩序的罪魁祸首,部分不法内容甚至给网民造成了一定的財产损失.在这样的 ...

  8. python 3.4.0 简单的print &#39;hello world&#39;,出错--SyntaxError: invalid syntax

    问题描写叙述: win7下安装的python 3.4.0版本号, 在命令行里写入简单的输出语句: print 'hello world' 然后enter,结果返回结果为: SyntaxError: i ...

  9. RS-232协议和RS-485协议

    RS232 RS232是一种异步传输标准接口.通常 RS-232 接口以9个引脚 (DB-9) 或是25个引脚 (DB-25) 的型态出现 .RS232最经常使用的连接方式是三根线:一条发送线.一条接 ...

  10. [.Net Tools] 超強大的封裝工具 Advanced Installer

    原文:[.Net Tools] 超强大的封装工具Advanced Installer 日前在网路上晃到这家公司的产品http://www.advancedinstaller.com/,就直接下载并且安 ...