首页 > 其他分享 >【c语言】自定义类型:联合体(公用体)【详解】

【c语言】自定义类型:联合体(公用体)【详解】

时间:2024-04-05 23:31:08浏览次数:28  
标签:自定义 int 联合体 char union 详解 printf un

联合体

联合体类型的声明

  1. 像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共用体
  2. 给联合体其中⼀个成员赋值,其他成员的值也跟着变化。
  3. 程序演示:
#include <stdio.h>

union Un
{
	char c;
	int i;
};

int main()
{
	//定义联合体变量
	union Un un = { 0 };
	//计算连个变量的⼤⼩
	printf("%d\n", sizeof(un));

	return 0;
}

为什么是4呢?大家可以思考一下

联合体的特点

  1. 联合的成员是共⽤同⼀块内存空间 的,这样⼀个联合变量的大小,⾄少是最⼤成员的大小(因为 联合⾄少得有能⼒保存最⼤的那个成员 )。
  2. 代码1
  3. #include <stdio.h>
    
    union Un
    {
    	char c;
    	int i;
    };
    
    int main()
    {
    	union Un un = { 0 };
    
    	printf("un.c--%p\n", &(un.c));
    	printf("un.i--%p\n", &(un.i));
    	printf("un----%p\n", &un);
    
    	return 0;
    }

    代码2

    #include <stdio.h>
    
    union Un
    {
    	char c;
    	int i;
    };
    
    int main()
    {
    	//联合变量的定义
    	union Un un = { 0 };
    
    	un.i = 0x11223344;
    	un.c = 0x55;
    
    	printf("%x\n", un.i);
    	return 0;
    }

    数据在内存中是小端存储(大小端存储详解),由于un.i和un.c占用的是同一块内存,首先给这块内存空间赋值0x11223344,然后赋值0x55,55覆盖了44

相同成员的结构体和联合体对比

  1. 我们再对⽐⼀下相同成员的结构体和联合体的内存布局情况。 
struct S
{
	char c;
	int i;
};

struct S s = { 0 };

union Un
{
	char c;
	int i;
};

union Un un = { 0 };

联合体大小的计算

  1. 联合的大小⾄少是最⼤成员的⼤⼩
  2. 当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍
#include <stdio.h>

union Un1
{
	char c[5];
	int i;
};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	//下⾯输出的结果是什么?

	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));

	return 0;
}

使用联合体是可以节省空间的,举例:

⽐如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。 那我们不耐⼼思考,直接写出⼀下结构:
struct gift_list
{
	//公共属性
	int stock_number;//库存量
	double price; //定价
	int item_type;//商品类型

	//特殊属性
	char title[20];//书名
	char author[20];//作者
	int num_pages;//⻚数

	char design[30];//设计
	int colors;//颜⾊
	int sizes;//尺⼨
};
上述的结构其实设计的很简单,⽤起来也⽅便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的⼤⼩就会偏⼤,⽐较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常⽤的。⽐如: 商品是图书,就不需要design、colors、sizes。 所以我们就可以把公共属性单独写出来,剩余属于各种商品本⾝的属性使⽤联合体起来,这样就可以介绍所需的内存空间,⼀定程度上节省了内存。
struct gift_list
{
	int stock_number;//库存量
	double price; //定价
	int item_type;//商品类型

	union {
		struct
		{
			char title[20];//书名
			char author[20];//作者
			int num_pages;//⻚数
		}book;
		struct
		{
			char design[30];//设计
		}mug;
		struct
		{
			char design[30];//设计
			int colors;//颜⾊
			int sizes;//尺⼨
		}shirt;
	}item;
};

联合的一个练习

写⼀个程序,判断当前机器是⼤端?还是⼩端?
#include <stdio.h>

int check_sys()
{
	union
	{
		int i;
		char c;
	}un;

	un.i = 1;

	return un.c;//返回1是⼩端,返回0是⼤端
}

int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}

	return 0;
}

标签:自定义,int,联合体,char,union,详解,printf,un
From: https://blog.csdn.net/weixin_52978505/article/details/137348558

相关文章

  • Linux 用户、用户组 useradd、groupadd等详解
    ......
  • Autosar-BswM 配置详解(免费)-2
    上表配置内容的意思是,BswM初始化过程中会先走到“BswM_AR_InitBlockTwo”这个步骤,如果条件满足的话,会执行这个步骤所有的动作。执行完后“BswM_AR_InitBlockTwo”,会切换到“BswM_AR_ReadAllComplete”这个步骤,如果条件满足的话,执行完该步骤的所有动作。之后再次切换到run的......
  • [C++][C++11][智能指针]分析详解 + 代码模拟
    目录0.智能指针三要素:)1.为什么需要智能指针?2.内存泄漏1.什么是内存泄漏?内存泄漏的危害?2.内存泄漏分类(了解)3.如何检测内存泄漏4.如何避免内存泄漏3.RAII4.智能指针原理5.auto_ptr(失败设计)6.unique_ptr7.shared_ptr1.实现原理:通过引用计数的方式来实现多个shared_ptr......
  • 数据结构:详解【树和二叉树】
    1.树的概念及结构(了解)1.1树的概念树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。1.2树的结构1.3树与非树:1.4树在实际中的运用(表示文件系统的目录树结构)2.......
  • C#–特性详解
    一、特性是什么1、特性定义特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([])来描述的。特性(Attribute)用于添加元数......
  • C#-反射详解
    一、反射是什么1、C#编译运行过程高级语言->编译->dll/exe文件->CLR/JIT->机器码2、原理解析metadata:元数据数据清单,记录了dll中包含了哪些东西,是一个描述。IL:中间语言,编译把高级语言编译后得到的C#中最真实的语言状态,面向对象语言。反射:来自于System.Reflection,是一个帮助类......
  • C#泛型详解
    一、什么是泛型泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能。我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样。但我们没有办法,只能分别写多个方法来处理不同的数据类型。这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入......
  • VisualStduio如何自定义代码片段
    什么是代码片段代码片段又叫CodeSnippet,可以用来快捷补全代码。其实我们经常使用这个功能。比如for循环,输入for会弹出这个窗口 我们选择第二个for,再按两次Tab键,编辑器就会自动生成完整的for循环代码。代码片段怎么使用注意蓝色的i方块,我们输入其他循环变量,再按下Tab键,所......
  • Android 14.0 添加自定义服务,并生成jar给第三方app调用
    1.概述在14.0系统ROM产品定制化开发中,由于需要新增加自定义的功能,所以要增加自定义服务,而app上层通过调用自定义服务,来调用相应的功能,所以系统需要先生成jar,然后生成jar给上层app调用,接下来就来分析实现的步骤,然后来实现相关的功能从而来实现所需要的功能2.关于添加系统......
  • 预处理详解
    一.预定义符号在C语言里设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间使用的。__FILE__:进行编译的源文件__LINE__:文件当前行号__DATE__:文件被编译的日期__TIME__:文件被编译的时间__STDC__:如果编译器遵循ANSIC,其值为1,否则未定义我们可以直接使用这些符......