C 语言结构体赋值分析和其优点(使用方式和汇编分析)

1. 例子

#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Foo
{char a;int b;double c;
};int main()
{// 定义结构体对象struct Foo foo1;struct Foo foo2;// 初始化为 0memset(&foo1, 0, sizeof(foo1));memset(&foo2, 0, sizeof(foo2));// 初始 foo1 的值foo1.a = 'a';foo1.b = 1;foo1.c = 3.14;// 结构体赋值:将 foo1 赋值给 foo2foo2 = foo1;memcpy(&foo2, &foo1, sizeof(foo1));// 打印 foo2 的值printf("%c   %d   %lf\n", foo2.a, foo2.b, foo2.c); // a   1   3.140000return 0;
}

上面我们定义的两个结构体,给第一个结构体 foo1 赋值初始化,然后我们将第一个结构体直接复制给第二个结构体,这一段代码是能够正常运行的,另外,我们使用 memcpy 这个函数将第一个结构体复制给第二个结构体它们的功能是一样的。

2. 反汇编

2.1 gcc 汇编

我们可以通过反汇编的方法看一下这两种方式,哪一种方式的效率更高。

在这里插入图片描述

在结构体赋值中,

foo2 = foo1;

生成的汇编:

        mov     rax, QWORD PTR [rbp-16]mov     rdx, QWORD PTR [rbp-8]mov     QWORD PTR [rbp-32], raxmov     QWORD PTR [rbp-24], rdx

对比在 gcc 中,

memcpy(&foo2, &foo1, sizeof(foo1));

生成的汇编是一样的:

        mov     rax, QWORD PTR [rbp-16]mov     rdx, QWORD PTR [rbp-8]mov     QWORD PTR [rbp-32], raxmov     QWORD PTR [rbp-24], rdx

其实这是 gcc 编译器优化的结果,但也能看出,结构体赋值,是将 foo1 的内容,按寄存器的大小,在这里是 8 个字节,以每次8个字节的复制到 foo2。假如说你是开发编译器的人,这已经是机器所能达到的最优解了。

2.2 VS clang 汇编

在这里插入图片描述
在结构体赋值中,

foo2 = foo1;

生成的汇编就是将 foo1 的数据每次通过寄存器按寄存器的大小赋值给 foo2:

        mov     edx, DWORD PTR _foo1$[ebp]mov     DWORD PTR _foo2$[ebp], edxmov     eax, DWORD PTR _foo1$[ebp+4]mov     DWORD PTR _foo2$[ebp+4], eaxmov     ecx, DWORD PTR _foo1$[ebp+8]mov     DWORD PTR _foo2$[ebp+8], ecxmov     edx, DWORD PTR _foo1$[ebp+12]mov     DWORD PTR _foo2$[ebp+12], edx

而使用 clang DEBUG 模式进行反汇编时,会调用 memcpy 函数

memcpy(&foo2, &foo1, sizeof(foo1));

生成的汇编:

        push    16                                  ; 00000010Hlea     eax, DWORD PTR _foo1$[ebp]push    eaxlea     ecx, DWORD PTR _foo2$[ebp]push    ecxcall    memcpy

调用 memcpy 这个函数时的耗时就大于上面的结构体赋值了。

我们看一下它的源码,这个就是按字节赋值,没有经过优化:

void *memcpy(void *dst, const void *src, size_t len)
{if(NULL == dst || NULL == src){return NULL;}void *ret = dst;if(dst <= src || (char *)dst >= (char *)src + len){//没有内存重叠,从低地址开始复制while(len--){*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;}}else{//有内存重叠,从高地址开始复制src = (char *)src + len - 1;dst = (char *)dst + len - 1;while(len--){*(char *)dst = *(char *)src;dst = (char *)dst - 1;src = (char *)src - 1;}}return ret;
}

3. 总结

结构体赋值是 C 语言中一个很好用的特性。

  1. 它不需要 memcpy 调用那么复杂
  2. 它已经经过了编译器优化,以最快的方式运行。
  3. 在结构体数组中,如果需要对结构体数组的元素进行排序时,使用结构体赋值具有很好的可读性,它让你写起代码就像是对一个整型数组进行排序一样。
  4. 结构体赋值在使用时编译器可以对类型进行判断,可以在编译时就预防错误。而 memcpy 使用起来一个参数也不能输错,容易造成错误。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes/K8s集群1.23.6搭建

1 集群规划 HostnameIP角色centos702192.168.131.102mastercentos704192.168.131.104nodecentos705192.168.131.105node 2 安装步骤 初始操作和安装基础软件每个节点都要执行。 2.1 初始操作 2.1.1 关闭防火墙 systemctl stop firewalld systemctl disable firewalld2.1.…

Science Robotics 受鳞片启发的可编程机器人结构,可同时进行形状变形和刚度变化

一、前言速览 生物有机体通常凭借复杂的结构表现出显著的多功能性&#xff0c;例如章鱼具有可以同时改变形状和刚度的能力。现有的仿生软体机器人要想实现这样的能力&#xff0c;往往需要繁琐的结构和复杂的控制系统。为此&#xff0c;来自新加坡南洋理工大学的研究人员从覆盖…

ARM高性能计算(HPC)处理器Neoverse介绍

思考: Neoverse系列中的N、V、E有什么区别? 这三个字母的缩写又是什么? ARM Neoverse架构是ARM专为服务器、数据中心、高性能计算(HPC)和网络基础设施设计的一系列处理器架构。Neoverse架构分为N系列、V系列和E系列,这些系列面向不同的应用场景,各自有不同的设计目标和…

44 个 React 前端面试问题

1.你知道哪些React hooks&#xff1f; useState&#xff1a;用于管理功能组件中的状态。useEffect&#xff1a;用于在功能组件中执行副作用&#xff0c;例如获取数据或订阅事件。useContext&#xff1a;用于访问功能组件内的 React 上下文的值。useRef&#xff1a;用于创建对跨…

人工智能新纪元

人类社会正式从信息科技时代步入了人工智能时代&#xff0c;相比信息科技革命&#xff0c;人工智能科技革命的影响要深远的多&#xff0c;在这新旧交替剧烈变革期&#xff0c;绝大多数人都有机会。 为了更好的理解人工智能科技革命&#xff0c;首先我们首先梳理一下技术的发展…

全网最最最详细的haproxy详解!!!

1 什么是负载均衡 负载均衡&#xff08;Load Balancing&#xff09;是一种将网络请求或工作负载分散到多个服务器或计算机资源上的技术&#xff0c;以实现优化资源使用、提高系统吞吐量、增强数据冗余和故障容错能力、以及减少响应时间的目的。在分布式系统、云计算环境、Web服…

ArkUI---Swiper、Grid、List组件简单介绍

前言&#xff1a;ForEach ForEach语法如下&#xff1a; ForEach(arr: Array,itemGenerator: (item: Array, index?: number) > void,keyGenerator?: (item: Array, index?: number) : string > string ) 参数1&#xff1a;数据源&#xff0c;为Array的数组 参数2&am…

KOLA: CAREFULLY BENCHMARKING WORLD KNOWLEDGE OF LARGE LANGUAGE MODELS

文章目录 题目摘要简介KOLA 基准实验评估结论和未来工作道德声明 题目 KOLA&#xff1a;仔细对大型语言模型的世界知识进行基准测试 论文地址:https://arxiv.org/abs/2306.09296 项目地址:https://github.com/ranahaani/GNews 摘要 大型语言模型 (LLM) 的卓越性能要求评估方法…

Grok-2的Beta版发布

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

图论------Bellman-Ford算法求单源最短路径的优化

目录 前情回顾&#xff1a; 画图分析&#xff1a; 具体代码&#xff1a; 前情回顾&#xff1a; 大家是否还记得我们之前讲过的Bellman-Ford算法&#xff0c;如果忘记的话可以点击链接去复习一下&#xff1a;图论------贝尔曼-福德&#xff08;Bellman-Ford&#xff09;算法-…

8月13日学习笔记 LVS

一.描述以及工作原理 1. 什么是LVS linux virtural server的简称&#xff0c;也就是linxu虚拟机服务器&#xff0c;这是一个 由章文嵩博士发起的开源项目&#xff0c;官网是 http://www.linuxvirtualserver.org,现在lvs已经是linux内核标 准的一部分&#xff0c;使用lvs可以达…

杭州网络安全等保测评——数据守护者的金盾牌️

在数字化转型疾驰的杭州&#xff0c;网络疆域的每一次拓展都伴随着安全风险的增长。如何在创新与安全之间找到黄金平衡点&#xff1f;《杭州等保测评&#xff1a;守护网络安全的坚实屏障》一文&#xff0c;深入探索这座智慧城市如何依托等保测评体系&#xff0c;构建起一道道安…

【已EI检索会议】第五届新材料与清洁能源国际学术会议(ICAMCE 2024)

重要信息 会议官网&#xff1a;2024.icceam.com 接受/拒稿通知&#xff1a;投稿后1周内 收录检索&#xff1a;EI, Scopus 会议召开视频 见刊封面 EI检索页面 Scopus 检索页面 相关会议 第六届新材料与清洁能源国际学术会议&#xff08;ICAMCE 2025&#xff09; 大会官网&…

机器学习常用包numpy篇(二)数组属性与基本操作

目录 前言 数组属性 1.数组转置 2.数组元素的数据类型 3.数组元素的虚部 4.数组元素的实部 5.数组包含的元素个数 6.数组元素的字节数 7.数组元素的总字节 8.数组维度 9.数组形状 10.每个维度中步进的字节数组 11.数组维度和形状 数组基本操作 1.重设形状 2.数…

【vue3|第23期】Vite + Vue3: 深入理解public和assets文件夹的作用与使用

日期&#xff1a;2024年8月14日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

GBJ406-ASEMI无人机专用GBJ406

编辑&#xff1a;ll GBJ406-ASEMI无人机专用GBJ406 型号&#xff1a;GBJ406 品牌&#xff1a;ASEMI 封装&#xff1a;GBJ-4 批号&#xff1a;2024 现货&#xff1a;50000 最大重复峰值反向电压&#xff1a;600V 最大正向平均整流电流(Vdss)&#xff1a;4A 功率(Pd)&am…

“从零开始的HTML 表格”——WEB开发系列09

HTML 表格是一种用于在网页上组织和显示信息的结构性元素&#xff0c;它能够将数据以行和列的形式呈现&#xff0c;帮助用户更清晰地理解数据关系。表格在展示统计数据、产品列表、日程安排等方面非常实用。 一、HTML 表格的基本结构 HTML 表格用 ​​<table>​​ 标签来…

day36——homework

二、基于UDP的TFTP文件传输 1&#xff09;tftp协议概述 简单文件传输协议&#xff0c;适用于在网络上进行文件传输的一套标准协议&#xff0c;使用UDP传输 特点&#xff1a; 是应用层协议 基于UDP协议实现 数据传输模式 octet&#xff1a;二进制模式&#xff08;常用&am…

MySQL源码安装与MySQL基础学习

1、安装MySQL ​ 本次安装使用的是绿色硬盘版本&#xff0c;无需额外安装依赖环境&#xff0c;比较简单 修改相关配置文件&#xff1a; 设置环境变量&#xff0c;声明/宣告MySQL命令便于系统识别&#xff1a; 初始化数据库&#xff1a; 设置系统识别&#xff0c;进行操作&…

Java基础之隐式类型转换

类型转换 基本数据类型表示范围大小排序&#xff1a; 在变量赋值及算术运算的过程中&#xff0c;经常会用到数据类型转换&#xff0c;其分为两类&#xff1a; 隐式类型转换 显式类型转换 1 隐式类型转换 情形1&#xff1a;赋值过程中&#xff0c;小数据类型值或变量可以直…