结构体struct 与 联合union
1.C语言中的结构体
1.1 定义
结构体是由一系列相同或不同类型的变量组成的集合。
struct 结构体名{ //struct为关键字,“结构体名”为用户定义的类型标识。
数据类型1 成员名1; //{ }中是组成该结构体的成员,其中数据类型可以是C语言所允许的任何数据类型。
数据类型2 成员名2;
...
数据类型n 成员名n;
};
1.2 结构体的内存分配(方法一)
结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐。
原则1 数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
原则2 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
原则3 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
例1.
struct A{ struct B{
int a; char b;
char b; int a;
short c; short c;
}; }; sizeof(A) = ; int为4,char为1,short为2,这里用到了原则1和原则3。
sizeof(B) = ; char为1,int为4,short为2,怎么会是12?还是原则1和原则3。 a b c
A的内存布局:, *, b a c
B的内存布局:***, , **
其中星号*表示填充的字节。
A中,b后面为何要补充一个字节?因为c为short,其起始位置要为2的倍数,就是原则1。c的后面没有补充,因为b和c正好占用4个字节,整个A占用空间为4的倍数,也就是最大成员int类型的倍数,所以不用补充。
B中,b是char为1,b后面补充了3个字节,因为a是int为4,根据原则1,起始位置要为4的倍数,所以b后面要补充3个字节。c后面补充两个字节,根据原则3,整个B占用空间要为4的倍数,c后面不补充,整个B的空间为10,不符,所以要补充2个字节。
例2.
struct A{ struct B{
int a; char e[];
double b; int f;
float c; double g;
}; short h;
struct A i;
}; sizeof(A) = ; int为4,double为8,float为4,总长为8的倍数,补齐,所以整个A为24。 sizeof(B) = ; 看看B的内存布局。 e f g h
B的内存布局:* *, , , * * * * * *, i
* * * *, , * * * *
i其实就是A的内存布局。根据原则2,i的起始位置要为8的倍数,所以h后面要补齐。
1.3 结构体的内存分配(方法二)
struct的内存大小为每个数据内存的加和,首先按照最大的数据类型进行单个分配,如果前一个数据占用不了所有的内存,而剩下的内存可以放下下一个数据,则第二个数据不另外分配内存(但是地址必须是从这个数据类型大小的整数倍开始,看下面的struct C),否则重新分配一个最大类型的内存。(个人觉得这种方法比较好理解!)
例3.
struct A{ struct B{ struct C{
int a; int a; int a;
char b; double b; char b;
double c; char c; short c;
}; }; char d;
}
对于结构体A:
因为A中最大的数据类型是double,占8个字节。所以系统先分配8个字节用来放int,结果int只需要4个就够了,然后剩下的4个字节中的1个可以用来放后面的char,碰到double c时,因为此时的3个字节不能存下,所以再分配了一个8个字节来存放double c。因此A占用16个字节。
对于结构体B:
系统碰到int分给他8个字节存放,碰到double时,剩下的4个字节不足以存放,所以再分配了8个字节,再遇到char时又分配了8个字节,这样B共分配了24个字节。(系统其实是浪费了5个字节的空间)
比较A和B,只有变量定义的顺序不一样,结果占用的内存空间也不一样。所以,结构体里面最好按照类型从小到大的顺序来排列,以免浪费空间。
对于结构体C:
按照上述方法,最大的数据类型是int,占4个字节,系统先分配4个字节(0~3);再分配4个字节(4~7),存放char b;short c占2个字节,但是必须从2的整数倍开始,所以应当分配(6~7),中间空余1个字节;char d占1个字节,但是上次分配的4字节用完了,所以需要再分配4个字节存放char d,d只占用1个字节,所以剩下3个字节空闲。sizeof(struct C)=12。
2. C++中的结构体与类的区别
C中的结构体不允许有函数,而C++中的结构体允许。
类与结构体在C++中只有两点区别,除此这外无任何区别。
1)class中默认的成员访问权限是private的,而struct中则是public的。
2)从class继承默认是private继承,而从struct继承默认是public继承。
3. 联合union
3.1 定义
联合(又叫共用体)是一种特殊形式的变量,使用关键字union来定义 ,它的声明与变量定义与结构体十分相似。其形式为:
union 联合名
{
数据类型 成员名;
数据类型 成员名;
...
} 变量名;
联合表示几个变量共用一个内存位置,在不同的时间保存不同的数据类型和不同长度的变量。在union中,所有的联合成员共用一个空间,并且同一时间只能储存其中一个成员变量的值。
3.2 联合的内存分配
Union的大小为其内部所有变量的最大值,并且按照类型最大值的整数倍进行内存对齐。
union A union B union C union D
{ { { {
char c[]; char c[]; char c[]; char c;
char cc1; int i; double d; int i;
}u1; }u2; }u3; double d;
}u4;
union A :首先按照char c[10]分配10个字节,然后按照char的1个字节对齐,最终sizeof(u1)=10;
union B :首先按照char c[10]分配10个字节,然后按照int的4个字节对齐,最终sizeof(u2)=12; (大于等于10且能被4整除的最小的数,即12)
union C :首先按照char c[10]分配10个字节,然后按照doube的8个字节对齐,最终sizeof(u3)=16;(大于等于10且能被8整除的最小的数,即16)
union D:按照double分配8个字节,最终sizeof(u4)=8;
3.3 应用
在C/C++程序的编写中,当多个基本数据类型或复合数据结构要占用同一片内存时,我们要使用联合体;当多种类型,多个对象,多个事物只取其一时(我们姑且通俗地称其为“n 选1”),我们也可以使用联合体来发挥其长处。
union myun
{
struct { int x; int y; int z; }u;
int k;
}a;
int main()
{
a.u.x =;
a.u.y =;
a.u.z =;
a.k = ;
printf("%d %d %d\n",a.u.x,a.u.y,a.u.z);
return ;
}
union类型是共享内存的,以size最大的结构作为自己的大小,这样的话,myun这个结构就包含u这个结构体,而大小也等于u这个结构体的大小,在内存中的排列为声明的顺序x,y,z从低到高,然后赋值的时候,在内存中,就是x的位置放置4,y的位置放置5,z的位置放置6,现在对k赋值,对k的赋值因为是union,要共享内存,所以从union的首地址开始放置,首地址开始的位置其实是x的位置,这样原来内存中x的位置就被k所赋的值代替了,就变为0了,这个时候要进行打印,就直接看内存里就行了,x的位置也就是k的位置是0,而y,z的位置的值没有改变,所以应该是0,5,6。
4.结构体和联合的区别:
1)联合和结构体都是由多个不同的数据类型成员组成,但在任何同一时刻,联合只存放了一个被选中的成员,而结构体的所有成员都存在。
2)对于联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而对于结构体的不同成员赋值是互不影响的。
结构体struct 与 联合union的更多相关文章
- 结构体struct、联合体union、枚举类型enum
1.c语言中的类型 1)内置类型——char,short,int,float,double: 2)用户自定义类型(UDT)——struct结构体,union联合体,enum枚举类型 2.内存对齐 2. ...
- C和C++中结构体(struct)、联合体(union)、枚举(enum)的区别
C++对C语言的结构.联合.枚举 这3种数据类型进行了扩展. 1.C++定义的结构名.联合名.枚举名 都是 类型名,可以直接用于变量的声明或定义.即在C++中定义变量时不必在结构名.联合名.枚举名 前 ...
- 结构体struct和联合体union以及enum枚举体5的区别
下面来自wikipedia: In computer science, a union is a value that may have any of several representations ...
- C++学习(二十六)(C语言部分)之 结构体3(联合,枚举)
结构体 struct 类型定义点运算符 . 变量名.成员 成员是数组的时候不能用等于号赋值箭头运算符 -> 指针->成员 作用 存放多个不同类型的有关联的数据 与结构体类似的类型1.联合作 ...
- 结构体struct sockaddr_in, struct sockaddr,struct in_addr
一.结构体 struct sockaddr_in, struct sockaddr, struct in_addr struct sockaddr_in, struct sockaddr,str ...
- 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf
转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq 结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看 ...
- C语言结构体-struct
知识点: 1)结构体的定义. 2)结构体的sizeof. 3) 结构体的指针. 1) 结构体的定义: 在逻辑上有一定关联的多个数据类型做为一整体进行操作的数据结构,它的关键字是struct.下面我将 ...
- 内核中用于数据接收的结构体struct msghdr(转)
内核中用于数据接收的结构体struct msghdr(转) 我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,pin ...
- Swift中元组(Tuples),结构体(Struct),枚举(Enums)之间的区别
Swift有许多种存储数据方式,你可以用枚举(enums),元组(tuples),结构体(structs),类(classes),在这篇文章中我们将比较枚举.元组.结构体之间区别,首先从最简单的开始- ...
随机推荐
- iOS 渐变进度条
#import <UIKit/UIKit.h> @interface JianBianView : UIView //为了增加一个表示进度条的进行,可们可以使用mask属性来屏蔽一部分 @ ...
- css 修改滚动条
::-webkit-scrollbar { width: 10px;}::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 6px rgb ...
- SqlServer性能优化 提高并发性能(八)
并发访问: 当多个线程访问同一个资源,会产生并发性问题 并发控制与处理: 乐观并发控制:一种方式是"后来的更新者获胜" 这意味着先来的用户提交的值会在没有察觉的情况下丢失. 为 ...
- easyUI参数传递Long型8100131457085857579980953变成8.100131457085857e 24的问题,如下可以解决
function addOptBtn(val, row, index) { var ht = "<a href='${pageContext.request.contextPath}/ ...
- 研华运动控制卡 SoftMotion 技术简介
SoftMotion为研华在设备自动化中的一项重要核心技术,相较于过去市面上ASIC 运动控制解决方案,研华自动化团队自主技术开发软件运动控制技术,并且透过现场可程序逻辑门阵列 (FPGA, Fiel ...
- WIFI功率修改
1. 修改文件: mediatek/custom/工程/cgen/cfgdefault/CFG_WIFI_Default.h 2. 修改内容: {0x26, 0x26 ----- ...
- jquery检查元素存在性
javascript检查元素存在性: 即使这个元素被删除了,也不担心javascript代码报错: jquery检查元素存在性: 代码如下: if(!document.getElementById(& ...
- spring HandlerInterceptorAdapter拦截ajax异步请求,报错ERR_INCOMPLETE_CHUNKED_ENCODING
话不多说,直接上正文. 异常信息: Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING 问题描述: 该异常是在页面发送ajax请 ...
- Spring Application Event Example
Spring Application Event 项目结构 工程下载 https://github.com/xiaoheike/SpringApplicationEventExample.git Sp ...
- Neo4j批量插入(Batch Insertion)
新建一个maven工程,这里不赘述如何新建maven工程. 添加Neo4j jar到你的工程 有两种方式: 上网站官网下载jar包,根据自己的系统下载不同的压缩包,详细过程不描述,请自行搜索其他博客 ...