C语言中union与struct的区别及sizeof的计算方式
C语言中union与struct的区别
在C语言中结构体和联合具有细微差别,特别是使用sizeof()对其求大小时,许多刚刚接触C语言不久的朋友对此非常困惑,下面我将简单谈以下自己对union与struct之间的区别
联 合(union)
1. 联合说明和联合变量定义
联合也是一种新的数据类型, 它是一种特殊形式的变量。
联合说明和联合变量定义与结构十分相似。其形式为:
union 联合名{
数据类型 成员名;
数据类型 成员名;
...
} 联合变量名;
联合表示几个变量公用一个内存位置, 在不同的时间保存不同的数据类型 和不同长度的变量。
union A
{
int a[5];
char b;
double c;
}Air;
表示声明了一个名称为A的联合,可以使用A variable 来定义联合变量。
在联合变量 variable中 整型和字符型以及double型公用同一内存位置。
当一个联合被说明时, 编译程序自动地产生一个变量, 其长度为联合中最大的变量长度。
联合访问其成员的方法与结构相同。同样联合变量也可以定义成数组或指针,但定义为指针时, 也要用"->"符号, 此时联合访问成员可表示成:
联合名->成员名
另外, 联合既可以出现在结构内, 它的成员也可以是结构。
union
{
int i;
struct
{
char first;
char second;
}half;
}number;
2.结构的定义
定义一个结构的一般形式为:
struct 结构名
{
成员表列
};
成员表由若干个成员组成, 每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为:
类型说明符 成员名;
成员名的命名应符合标识符的书写规定。例如:
struct stu
{
int num;
char name[20];
char sex;
float score;
};
在这个结构定义中,结构名为stu,该结构由4个成员组成。第一个成员为num,整型变量;第二个成员为name,字符数组;第三个成员为 sex,字符变量;第四个成员为score,实型变量。 应注意在括号后的分号是不可少的。结构定义之后,即可进行变量说明。 凡说明为结构stu的变量都由上述4个成员组成。由此可见, 结构是一种复杂的数据类型,是数目固定,类型不同的若干有序变量的集合。
在介绍了结构和联合得基本知识后,我们开始今天要讲的关于sizeof对结构体和联合求值问题:
让我们来看一道华为的面试题:
例:设有以下说明和定义:
typedef union {long i; int k[5]; char c;} DATE;
struct data { int cat; DATE cow; double dog;} too;
DATE max;
则语句 printf( "%d",sizeof(struct date)+sizeof(max));的执行结果是:____
需要说明的是typedef只是一个简单的名字替换,方便系统在不同的平台上移植,请参考以下例子:
/*
Name: typedef
Copyright: reserved
Author: persever
Date: 02-08-11 03:51
Description:
*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
typedef int Example;
Example a=10;//Equals to int a=10;
printf("%d\n",a);
system("pause");
}
解释:假设为32位机器,那么DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20,data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32. 所以结果是 20 + 32 = 52.
再看下例:
设有以下说明和定义:
typedef union {double i; int k[5]; char c;} DATE;
struct data { int cat; DATE cow; double dog;} too;
DATE max;
则语句 printf( "%d",sizeof(struct date)+sizeof(max));的执行结果是:____
在草率回答这一问题之前我们先看一个小例子:
#include <stdio.h>
#include <stdlib.h>
union A
{
int a[5];
char b;
double c;
};
int main()
{
printf("%d\n",sizeof(A));
system("pause");
}
对A用sizeof输出却得到的是24!union中变量共用内存,应以最长的为准,可是结果却不是我们预想的20,这是因为在联合内变量的默认内存对其方式,必须以最长的double8字节对齐,也就是说故应该是sizeof(A)=24;所以我们将联合中的int a[5] 修改成 int a[6] 结果仍然不变,但如果我们将int a[5]修改成 int a[7],结果就变成了 32了。
struct AA
{
int num,*a;
char d;
double e;
};
int i1 = sizeof(int);//占用4个字节
int i2 = sizeof(int*);//占用4个字节
int i3 = sizeof(char);//占用1个字节
int i4 = sizeof(double);//占用8个字节
int i5 = sizeof(AA);//占用24字节
为什么结构体AA不是只用其成员的总和值4+4+1+8呢?
因为根据
Win32平台下的微软 编译器(cl.exe for 80×86)的对齐策略:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)。
备注:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。
是不是有点云里雾里呢?那让我们一起来遵循规律看下来吧
其中int i1 = sizeof(int)//偏移量为0 占用4个字节的长度
int i2 = sizeof(int*)//下一个偏移量为4(满足规则2)是i2=4 的整数倍
int i3 = sizeof(char);//下一个偏移量为8(满足规则2)是i=1 的整数倍
int i4 = sizeof(double);//下一个偏移量为9(不满足规则1)不能被 i4 = 8所正除,所以应当9+7 = 16
所以总数为16+i4(8)= 24(满足条件3)
所以为24
是否已经明白呢??
不凡再看以下代码
struct MyStruct
{
char dda;//偏移量为0,满足对齐方式,dda占用1个字节;
double dda1; //下一个可用的地址的偏移量为1,不是sizeof(double)=8
//的倍数,需要补足7个字节才能使偏移量变为8(满足对齐
//方式),因此VC自动填充7个字节,dda1存放在偏移量为8
//的地址上,它占用8个字节。
int type; //下一个可用的地址的偏移量为16,是sizeof(int)=4的倍
//数,满足int的对齐方式,所以不需要VC自动填充,type存
//放在偏移量为16的地址上,它占用4个字节。
};
//所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构
//的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof
//(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为
//sizeof(double)=8的倍数。
其中要是不想遵循结构体对齐策略也可以用 #pragma pack 去掉内存对齐,去掉的话,应该会影响到效率吧。 万一在嵌入式下的话,有可能导致程序出错吧。
C语言中union与struct的区别及sizeof的计算方式相关推荐
- 面试珠玑 C语言中union与struct的区别及sizeof的计算方式
在C语言中结构体和联合具有细微差别,特别是使用sizeof()对其求大小时,许多刚刚接触C语言不久的朋友对此非常困惑,下面我将简单谈以下自己对union与struct之间的区别 联 合(union) ...
- c语言中 char怎样用,C语言中char*和char[]用法区别分析
C语言中char*和char[]用法区别分析 本文实例分析了C语言中char* 和 char []的区别.分享给大家供大家参考之用.具体分析如下: 一般来说,很多人会觉得这两个定义效果一样,其实差别很 ...
- 浅谈Java语言中ArrayList和HashSet的区别
Java语言中ArrayList和HashSet的区别 2019-04-10 13:22:49 一.基本区别 首先一起看个实例,其代码如下: package com.MrZ_baby.com; i ...
- union与struct的区别?
union与struct的区别? 1)union 维护足够的空间来置放多个数据成员中的"一种",而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间 ...
- c语言char有什么作用,C语言中char*和char[]用法区别分析
本文实例分析了C语言中char* 和 char []的区别.分享给大家供大家参考之用.具体分析如下: 一般来说,很多人会觉得这两个定义效果一样,其实差别很大.以下是个人的一些看法,有不正确的地方望指正 ...
- java.substr_Java语言中substr和substring的区别
Java语言中substr和substring的区别 由于在项目中有需要对字符串进行截取,然后手残使用了IDE自动提示的substr,没想那么多以为substr和substring没多大区别. 然而并 ...
- c语言中sbit什么意思,c语言中bit和sbit的区别.doc
c语言中bit和sbit的区别 c语言中bit和sbit的区别?? 1.bit和sbit都是C51扩展的变量类型. ??????? bit和int char之类的差不多,只不过char=8位, bit ...
- C语言中*p 和p的区别
C语言中*p 和p的区别 C语言中,*p 和p都常用在指针当中表示一个指针变量,*p 和p的区别: 表示的含义不同 *p表示此指针指向的内存地址中存放的内容. p表示一个指针变量的名字,指此指针变量所 ...
- c语言put语句的作用,C语言中put()与puts()的区别?
C语言中put()与puts()的区别? 关注:275 答案:2 mip版 解决时间 2021-02-04 15:47 提问者笑低了眉眼 2021-02-04 12:42 C语言中put()与pu ...
最新文章
- 互联网金融真能救汽车电商的梦吗?
- 如何告别那些没卵用的线上告警!
- 即使在jdk中也有错误的代码
- 视频AI对话杭州云栖:新一代视频智能生产的探索与实践
- Java高级编程之URL处理
- 数字图像处理的起源与应用
- BLUE引擎或者LEG引擎M2架设时提示【该授权文件已过期】原因和解决方法
- ffmpeg 博客-雷霄骅
- 一文读懂各种分布式机器学习框架的区别与联系
- Qt项目--截屏软件
- 含有隐函数的离散常微分方程求解
- 紫乌鸦服务器维护后多久刷,魔兽世界boss刷新时间(世界boss刷新机制详解)
- [深入研究4G/5G/6G专题-57]: L3信令控制-6-什么是无线承载DRB Profile
- 移动端iOS中input输入框搜索框软键盘出现换行而不是搜索
- 宾馆如何锁定计算机,酒店密码锁怎么反锁 公寓酒店密码门锁使用操作说明
- 宜家订单JSON_怎么评价宜家(IKEA)?
- H3C光模块相关命令和检测方法
- 常用的十大Python开发工具
- 使用 awk 处理一个对齐问题
- 108页《SpringBoot 学习笔记完整教程》PDF附下载
热门文章
- 摒弃盗版,让我们拥有正版,给你最实用的软件。有效的优化
- 【新版】模拟量输入模块的2、3、4线制的接法图解
- READ-2203 FLDetector: Defending Federated Learning Against Model Poisoning Attacks via Detecting Mal
- 问题 D: 神奇密码锁
- Redis 运维 三
- 跟着团子学SAP SD-RRB(按资源开票)流程演示及核心配置(DIP参数文件) DP80/DP81/DP90/DP91
- SRPG游戏开发(四十一)第九章 战斗系统 - 三 战斗动画(Combat Animation)
- Ubuntu16.04的安装教程
- 董藩:北京房价可以涨到每平米80万===如此高论,岂不保存下来,且待25年后再看...
- edx平台搭建(基于Ubuntu搭建edx)