C语言共用体详解

news2024/10/6 10:27:43

文章目录

    • 共用体解释
    • 代码说明
    • 小端存储 Little Endian
    • 共用体与小端存储
    • 为什么只能用第一个成员类型的值初始化一个共用体变量

共用体解释

共用体(Union)是一种特殊的数据类型,
它允许在同一个内存位置存储不同的数据类型。
共用体的所有成员共享同一块内存空间,
因此同一时间只能存储其中一个成员的值。

共用体的定义和结构体类似,使用关键字union,后面跟着成员列表。
每个成员可以是不同的数据类型,
但共用体的所有成员都共享同一块内存空间,大小取决于最大的成员

共用体的成员可以通过点操作符(.)或箭头操作符(->)来访问。

共用体的主要特点如下:

  1. 共用体的大小取决于最大的成员的大小。
  2. 共用体的成员共享同一块内存空间只能同时存储其中一个成员的值
  3. 对共用体的任何成员的修改都会影响到其他成员
  4. 共用体的成员可以具有不同的数据类型,但它们在内存中的起始位置是相同的

共用体的主要用途有:

  1. 节省内存空间:当多个成员变量不会同时使用,但需要共享同一块内存空间时,可以使用共用体来节省内存。
  2. 数据类型转换:共用体可以用于不同类型之间的转换,通过存储一个成员变量,然后通过另一个成员变量来读取转换后的值。

需要注意的是,由于共用体的成员共享同一块内存空间,因此在使用共用体时需要谨慎处理成员的赋值和读取操作,以免出现意外的结果。

代码说明

#include <stdio.h>

// 定义一个共用体
union Data {
    int i;
    float f;
    char str[20];
};

int main() {
    union Data data;
    
    // 修改共用体的成员
    data.i = 10;
    printf("data.i: %d\n", data.i);
    
    data.f = 3.14;
    printf("data.f: %f\n", data.f);
    
    strcpy(data.str, "Hello");
    printf("data.str: %s\n", data.str);
    
    // 访问共用体的成员
    printf("data.i: %d\n", data.i);
    printf("data.f: %f\n", data.f);
    printf("data.str: %s\n", data.str);
    
    return 0;
}

输出

data.i: 10
data.f: 3.140000
data.str: Hello
data.i: 1819043144
data.f: 1143139122437582500000000000.000000
data.str: Hello

在这里插入图片描述

小端存储 Little Endian

小端存储(Little Endian)是一种计算机存储数据的方式,
其中较低有效字节(即数值的最低位字节)存储在较低的内存地址
较高有效字节存储在较高的内存地址
在这里插入图片描述

在小端存储中,多字节数据类型(如整数或浮点数)的字节顺序是从低位到高位。

例如,对于一个16位整数0x1234,存储在内存中的字节顺序是0x34(低地址)和0x12(高地址)。

小端存储的特点是:

  1. 较低有效字节存储在较低的内存地址,较高有效字节存储在较高的内存地址。
  2. 对于多字节数据类型,字节的顺序是从低位到高位。
  3. 可以通过简单的指针操作来访问和操作多字节数据类型的各个字节。

下面是一个示例代码,用于说明C语言中小端存储的特点:


#include <stdio.h>

int main() {
    unsigned int num = 0x12345678;
    unsigned char *ptr = (unsigned char*)&num;

    printf("num: 0x%x\n", num);
    
    printf("Byte order: ");
    for (int i = 0; i < sizeof(num); i++) {
        printf("%02x ", *(ptr + i));
    }
    printf("\n");

    return 0;
}

在上述代码中,我们定义了一个无符号整数num,并将其赋值为0x12345678。
然后,我们使用一个指向num的无符号字符指针ptr。

通过循环遍历指针ptr,我们打印出num中每个字节的值。
根据小端存储的特点,输出结果应该是:

num: 0x12345678
Byte order: 78 56 34 12

在这里插入图片描述

从输出结果可以看出,较低有效字节0x78存储在较低的内存地址,较高有效字节0x12存储在较高的内存地址,符合小端存储的字节顺序。

unsigned int num = 0x12345678;
十六进制的一个数字即4bit, 两个数字为8bit = 1Byte
char类型为1Byte, 即每次可以取出2个数字
所以是 78 56 34 12

在实际编程中,我们需要注意小端存储的影响,特别是在处理网络通信、文件IO和数据转换等场景下,需要正确处理字节顺序的转换。

在这里插入图片描述

大端存储与之相反, 这里不做介绍

共用体与小端存储

void test() {
    union  {
        short int i;
        char d[2];
    }r, *s=&r;
    s->i = 0x1234;
    printf("%x\n", s->i);  // 1234
    printf("%x, %x\n", s->d[0], s->d[1]);  // 34, 12
}

为什么只能用第一个成员类型的值初始化一个共用体变量

在C语言中,共用体(union)的所有成员共享同一块内存空间。

因此,共用体的大小和内存布局是根据它的成员类型来确定的。

当我们初始化一个共用体变量时,需要指定其中一个成员的值,
这样编译器才知道如何正确地分配内存和解释这块内存中的内容。

由于共用体的所有成员共享同一块内存,
因此使用不同类型的值来初始化共用体变量可能会导致问题。
如果我们使用非第一个成员类型的值来初始化共用体变量,
编译器无法准确地确定应该如何解释这块内存中的内容。
这可能会导致未定义的行为,
例如访问无效的内存或得到不正确的结果。

因此,为了确保正确的内存布局和避免未定义的行为,
C语言规定只能使用第一个成员类型的值来初始化共用体变量。

第一个成员类型的值来初始化
第一个成员类型的值来初始化
第一个成员类型的值来初始化

这样编译器就能正确地分配内存
并根据第一个成员类型来解释这块内存中的内容。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/977258.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ICCOA蓝牙数字车钥匙2.0

近期&#xff0c;ICCOA智慧车联开放联盟宣布&#xff0c;由小米、vivo、OPPO、长安、深蓝、吉利、极氪、比亚迪、北汽、蔚来、零跑、雪球、瓶钵、融卡等企业联合参与制定的ICCOA蓝牙数字车钥匙2.0标准&#xff08;简称DK2.0&#xff09;&#xff0c;于2023年9月1日正式发布实施…

【网络编程·数据链路层】MAC帧/以太网协议/ARP协议/RARP协议

需要云服务器等云产品来学习Linux的同学可以移步/-->腾讯云<--/-->阿里云<--/-->华为云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、MAC帧 1、IP地址和MAC地址的区别 2、MAC帧协议 3、MTU对IP协议的…

Python 3.x标准数据类型

文章目录 一、数字1.1 基本的数字类型有:1.2 整数数字表示方式二、字符串2.1 操作符2.2 格式化百分号format 格式化输出位置匹配2.3 字符串 索引和切片2.4 切片:字符串 [ 起始索引:终止索引:步长 ]字符串连接操作三、列表3.1 列表的定义3.2 常用方法(功能:增删改查)增删除…

S7-1200/1500增量式PID(输出归一化、支持PWM输出)

离散增量式PID算法公式请查看下面文章链接: 三菱PLC增量式PID算法FB(带死区设置和外部复位控制)_用三菱plc自己编写pid算法_RXXW_Dor的博客-CSDN博客关于PID废话不多说,各种位置式增量式资料和公式网上也非常多。PID从提出和发展目前已经一个世纪过去了,还在不断研究创新,…

使用Puppeteer构建博客内容的自动标签生成器

导语 标签是一种用于描述和分类博客内容的元数据&#xff0c;它可以帮助读者快速找到感兴趣的主题&#xff0c;也可以提高博客的搜索引擎优化&#xff08;SEO&#xff09;。然而&#xff0c;手动为每篇博客文章添加合适的标签是一件费时费力的工作&#xff0c;有时候也容易遗漏…

【SpringBoot应用篇】SpringBoot集成MinIO对象存储服务

【SpringBoot应用篇】SpringBoot集成MinIO对象存储服务 对象存储服务MinIOMinIO简介MinIO特点开箱使用docker安装启动管理控制台 快速入门Java 上传文件到minio配置访问权限 封装MinIO为starter创建模块zy-minio-starter配置类封装操作minIO类对外加入自动配置其他微服务使用 安…

好绝一数据可视化工具,零编程“BI+方案”

在一开始的时候&#xff0c;国外BI数据可视化工具的使用人群圈定在IT人员身上&#xff0c;所以我们可以看到国外BI数据可视化工具对使用者的IT技术要求较高&#xff0c;真正具有强烈数据分析需求的业务们反而无法按需分析。而现在&#xff0c;随着国产BI的崛起&#xff0c;面向…

Java线程概述 (二)线程实例演示

文章目录 &#x1f412;个人主页&#x1f3c5;JavaSE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;创建线程的三种方式&#x1f415;使用java.lang包下的Thread类&#x1fa85;实现Runnable接口&#x1f993;实现Callable接口 &#x1f415;synchronized简单介绍&#x…

Java手写数组队列和链表队列并使用java里面现成的队列方法

Java队列实现与常用使用方法介绍 说明使用数组手动实现队列功能使用单向链表手动实现队列功能Java中ArrayBlockingQueue和ArrayQueue和LinkedBlockingQueue使用ArrayQueue使用方法如下:ArrayBlockingQueue常用使用方法如下:LinkedBlockingQueue常用使用方法如下:ArrayBlockingQ…

Spring-mvc的参数传递与常用注解的解答及页面的跳转方式---综合案例

目录 一.slf4j--日志 二.常用注解 2.1.RequestMapping 2.2.RequestParam 2.3.RequestBody 2.4.PathVariable 三.参数的传递 3.1 基础类型 3.2 复杂类型 3.3 RequestParam 3.4 PathVariable 3.5 RequestBody 3.6 增删改查 四.返回值 4.1 void 返回值 4.2 String 返…

用go实现dns请求

一、DNS报文格式详解 1.1 报文格式 DNS分为查询请求和查询响应&#xff0c;两者的报文结构基本相同。DNS报文格式如下表展示 0 1516 31事务ID&#…

CVE-2023-28303(截图修复)

在做羊城杯的misc的时候发现了一个图片&#xff0c;典型的图片高度不对&#xff0c;修改之后对图片的高度进行不断修改尝试&#xff0c;发现图片很大&#xff0c;但是内容没有出现&#xff0c; 从这里指知道存在feld文件x 截出zip文件内容&#xff0c;把04 03 改为03 04 这里的…

SOLIDWORKS放样是什么意思?

SOLIDWORKS是一款广受欢迎的三维计算机辅助设计&#xff08;CAD&#xff09;软件&#xff0c;提供了许多强大的功能来帮助工程师实现他们的创意。其中一个重要的功能是放样功能&#xff0c;它在设计过程中起着至关重要的作用。本文将介绍SOLIDWORKS放样的概念、特点和应用。 放…

怎么将火狐浏览器中的书签或密码迁移到谷歌浏览器

文章目录 一、点击谷歌浏览器右上角二、选择书签–导入书签和设置…三、点击导入 一、点击谷歌浏览器右上角 二、选择书签–导入书签和设置… 在下拉框中选中Firefox&#xff0c;点击导入 三、点击导入

sublime text 格式化json快捷键配置

以 controlcommandj 为例。 打开Sublime Text&#xff0c;依次点击左上角菜单Sublime Text->Preferences->Key Bindings&#xff0c;出现以下文件&#xff1a; 左边的是Sublime Text默认的快捷键&#xff0c;不可编辑。右边是我们自定义快捷键的地方&#xff0c;在中括号…

手机便签功能在哪里?如何在便签里添加文字图片视频?

手机已成为我们生活中不可或缺的工具&#xff0c;而在使用手机的过程中&#xff0c;我们经常需要随手记录一些重要的事情。那么&#xff0c;如何高效便捷地记录这些事情呢&#xff1f;答案就是使用手机便签软件。但是&#xff0c;有很多人不知道手机便签功能在哪里&#xff1f;…

使用scp在两个linux系统之间传输文件

使用scp在两个linux系统之间传输文件 问题背景拷贝文件首先我们要从源设备&#xff08;本文中是矩池云自己的服务器&#xff09;传输文件至目标设备&#xff08;本文中是A100设备&#xff09;传输一个文件传输一个文件夹 从目标设备&#xff08;本文中是A100设备&#xff09;下…

Python基础之高级函数

异常捕获 Python中&#xff0c;使用trycatch两个关键字来实现对异常的处理。在我们平时的工作中&#xff0c;异常的出现是在所难免的&#xff0c;但是异常一旦出现&#xff0c;极有可能会直接导致程序崩溃&#xff0c;无法正常运行&#xff0c;所以异常一定要及时的做出对应的…

QT(9.5)QT连接OpenCV库完成人脸识别,c语言中的static和c++中的static的用法,在c和c++中const关键字的用法,Qt中基于TCP通信中的服务器和客户端的操作

1.QT完成人脸识别 pro文件: 头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> #include<opencv2/face.hpp> #include <vector> #include <map&g…

【STL】模拟实现map和set {map和set的封装;核心结构;插入和查找;红黑树的迭代器;STL中的红黑树结构}

模拟实现map和set map和set是红黑树的两种不同封装形式&#xff0c;底层使用同一颗泛型结构的红黑树&#xff0c;只是存储类型不同。set是红黑树的K模型&#xff0c;存储key&#xff1b;map是红黑树的KV模型&#xff0c;存储pair<key,value>。 下面的代码和讲解着重体现…