浅谈C语言中的联合体
联合体union
当多个数据须要共享内存或者多个数据每次仅仅取其一时。能够利用联合体(union)。在C Programming Language 一书中对于联合体是这么描写叙述的:
1)联合体是一个结构;
2)它的全部成员相对于基地址的偏移量都为0;
3)此结构空间要大到足够容纳最"宽"的成员;
4)其对齐方式要适合当中全部的成员;
以下解释这四条描写叙述:
因为联合体中的全部成员是共享一段内存的。因此每一个成员的存放首地址相对于于联合体变量的基地址的偏移量为0。即全部成员的首地址都是一样的。
为了使得全部成员可以共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合当中全部的成员”是指其必须符合全部成员的自身对齐方式。
以下举例说明:
如联合体
union U
{
char s[9];
int n;
double d;
};
s占9字节,n占4字节,d占8字节。因此其至少需9字节的空间。然而事实上际大小并非9,用运算符sizeof測试其大小为16.这是由于这里存在字节对齐的问题,9既不能被4整除。也不能被8整除。因此补充字节到16,这样就符合全部成员的自身对齐了。
从这里能够看出联合体所占的空间不仅取决于最宽成员。还跟全部成员有关系。即其大小必须满足两个条件:1)大小足够容纳最宽的成员;2)大小能被其包括的全部基本数据类型的大小所整除。
測试程序:

/*測试联合体 2011.10.3*/
#include <iostream>
using namespace std;
union U1
{
char s[9];
int n;
double d;
};
union U2
{
char s[5];
int n;
double d;
};
int main(int argc, char *argv[])
{
U1 u1;
U2 u2;
printf("%d\n",sizeof(u1));
printf("%d\n",sizeof(u2));
printf("0x%x\n",&u1);
printf("0x%x\n",&u1.s);
printf("0x%x\n",&u1.n);
printf("0x%x\n",&u1.d);
u1.n=1;
printf("%d\n",u1.s[0]);
printf("%lf\n",u1.d);
unsigned char *p=(unsigned char *)&u1;
printf("%d\n",*p);
printf("%d\n",*(p+1));
printf("%d\n",*(p+2));
printf("%d\n",*(p+3));
printf("%d\n",*(p+4));
printf("%d\n",*(p+5));
printf("%d\n",*(p+6));
printf("%d\n",*(p+7));
return 0;
}

输出结果为:
16
8
0x22ff60
0x22ff60
0x22ff60
0x22ff60
1
0.000000
1
0
0
0
48
204
64
0
请按随意键继续. . .
对于sizeof(u1)=16。由于u1中s占9字节。n占4字节。d占8字节,因此至少须要9字节。其包括的基本数据类型为char。int,double分别占1。4,8字节,为了使u1所占空间的大小能被1,4,8整除。则需填充字节以到16。因此sizeof(u1)=16.
对于sizeof(u2)=8。由于u2中s占5字节。n占4字节,d占8字节,因此至少须要8字节。其包括的基本数据类型为char,int,double分别占1,4,8字节。为了使u2所占空间的大小能被1,4,8整除,不需填充字节,由于8本身就能满足要求。因此sizeof(u2)=8。
从打印出的每一个成员的基地址能够看出。联合体中每一个成员的基地址都同样。等于联合体变量的首地址。
对u1.n=1,将u1的n赋值为1后,则该段内存的前4个字节存储的数据为00000001 00000000 00000000 00000000
因此取s[0]的数据表示取第一个单元的数据,其整型值为1。所以打印出的结果为1.
至于打印出的d为0.000000愿意例如以下。因为已知该段内存前4字节的单元存储的数据为00000001 00000000 00000000 00000000,从上面打印结果48,204,64,0能够知道后面4个字节单元中的数据为00110000 11001100 01000000 00000000。因此其表示的二进 制浮点数为
00000000 01000000 11001100 00110000 00000000 00000000 00000000 00000001
对于double型数据,第63位0为符号位,62-52 00000000100为阶码,0000 11001100 00110000 00000000 00000000 00000000 00000001为尾数,依据其值知道尾数值约为0,而阶码为4-1023=-1019。因此其表示的浮点数为1.0*2^(-1019)=0.00000000000......。因此输出结果为0.000000。
浅谈C语言中的联合体的更多相关文章
- 浅谈C语言中的强符号、弱符号、强引用和弱引用
摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...
- 浅谈 C 语言中模块化设计的范式
今天继续谈模块化的问题.这个想慢慢写成个系列,但是不一定连续写.基本是想起来了,就整理点思路出来.主要还是为以后集中整理做点铺垫. 我们都知道,层次分明的代码最容易维护.你可以轻易的换掉某个层次上的某 ...
- 浅谈c语言中的堆
操作系统堆管理器管理: 堆管理器是操作系统的一个模块,堆管理内存分配灵活,按需分配. 大块内存: 堆内存管理者总量很大的操作系统内存块,各进程可以按需申请使用,使用完释放. 程序手动申请&释放 ...
- 浅谈C#语言中的各种数据类型,与数据类型之间的转换
什么是数据类型? 数据类型,百度百科是这样解释的:数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作.这样的解释对于一个初学者来说未必太过于深奥. 简单点说,数据类型就是不同长度的 ...
- 浅谈C语言中的强符号、弱符号、强引用和弱引用【转】
转自:http://www.jb51.net/article/56924.htm 首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引 ...
- 浅谈C语言中结构体的初始化
转自:http://www.jb51.net/article/37246.htm <代码大全>建议在变量定义的时候进行初始化,但是很多人,特别是新人对结构体或者结构体数组定义是一般不会初始 ...
- 转: 浅谈C/C++中的指针和数组(二)
转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ...
- 浅谈关于QT中Webkit内核浏览器
关于QT中Webkit内核浏览器是本文要介绍的内容,主要是来学习QT中webkit中浏览器的使用.提起WebKit,大家自然而然地想到浏览器.作为浏览器内部的主要构件,WebKit的主要工作是渲染.给 ...
- 浅谈Java语言环境搭建-JDK8
title: 浅谈Java语言环境搭建-JDK8 blog: CSDN data: Java学习路线及视频 1.What's the JDK,JRE JDK(Java Development Kit ...
随机推荐
- 调试Android USB遇到的令人费解的问题
上周参照网上代码,做了USB的初步探测程序,工作正常 .今天从硬件部拿到了一段例程,原本打算参考它来完善自己的程序.但运行之后总是报错,逐步跟进错误,进而发现了一个匪疑所思的问题.调试一天也未发现原因 ...
- QML嵌入到QWidget中方法
简介 嵌入方法有两种一种是直接拖控件,另一种是cpp代码动态生成, 控件方式 动态代码生成 QQuickWidget *m_quickWidget=new QQuickWidget(); QUrl s ...
- Strut2 和Spring MVC 文件上传对比
在Java领域中,有两个常用的文件上传项目:一个是Apache组织Jakarta的Common-FileUpload组件 (http://commons.apache.org/proper/commo ...
- MySQL for Excel用法
MySQL有一款工具“MySQL for Excel”它可以提供将Excel的数据导入MySQL,或者将MySQL的数据导出到Excel的功能.简而言之,使用MySQL for Excel可以通过Ex ...
- NOI 2014 感想
NOI2014结束了,我卡线登上了领奖台... 这是我第一次NOI,我觉得我收获了很多东西: 1.考前心态不重要,重要的是实力 真正考试的时候是顾不得想其他事情的 2.测试数据是人出的!不是随机的!不 ...
- 【随笔】这段时间没有写博客是因为一边看Qt5的帮助文档一边写小程序
长话短说,因为和做程序员的以前的同学联系了一下,知道自己有很多不足,加之接到一个培训机构的人打来的电话稍微打击了一下,虽然那个人满嘴跑火车想装做和我很谈得来,但是我依然看到了自己没有写过任何命令行以外 ...
- apache开源项目-- NiFi
Apache NiFi 是一个易于使用.功能强大而且可靠的数据处理和分发系统.Apache NiFi 是为数据流设计.它支持高度可配置的指示图的数据路由.转换和系统中介逻辑. 架构: 集群管理器: 主 ...
- 使用C#调用Python脚本,带参数列表 z
static void Main(string[] args) { string[] strArr;//参数列表 string sArguments = @"Pythons.py" ...
- C++类型引用浅析
C++类型引用浅析 引言 从最早被Bjarne Stroustrup 发明,作为C语言的扩展,到广为人知C++98标准,再到最新的C++11.C++14和C++17标准,C++一直在不断地进步.演化. ...
- openstack 制作大于2TB根分区自动扩容的CENTOS镜像
制作镜像的时候默认分的是30G空间 qemu-img create -f raw centos.img 30G 看官网文档安装完系统需要安装cloud-init和clout-utils包,本人安装了完 ...