C语言,数组循环哪家好,指针or下标?

在这里插入图片描述
日常工作中,我们经常会用到循环遍历数组元素。不考虑只能使用某一特定方式的情况下,有人喜欢用数组下标遍历,有人则喜欢用指针遍历。那么这两者是否有性能差异呢?

我们先来看两个例子:

代码一
/* a.c */
#include <stdio.h>
#include <sys/time.h>int main(void)
{char arr[1024000];int i = 0;struct timeval begin, end;gettimeofday(&begin, NULL);for (; i < sizeof(arr); ++i) {arr[i] = 'c';}gettimeofday(&end, NULL);printf("%lu(us)\n", (end.tv_sec*1000000+end.tv_usec)-(begin.tv_sec*1000000+begin.tv_usec));for (i = 0; i < sizeof(arr); ++i)fprintf(stderr, "%c\n", arr[i]);return 0;
}

代码很简单,我们定义了一个比较长的字符数组,然后遍历每个元素进行赋值,并统计时长。最后遍历数组输出赋值内容。

我们如下执行命令:

$ gcc -o a a.c
$ ./a 2>/dev/null

那么循环赋值的执行时间如何呢?我取个平均一点的结果:

3227(us)
代码二
/* b.c */
#include <stdio.h>
#include <sys/time.h>int main(void)
{char arr[1024000], *p = arr, *last = arr + sizeof(arr);int i;struct timeval begin, end;gettimeofday(&begin, NULL);for (; p < last; ++p) {*p = 'c';}gettimeofday(&end, NULL);printf("%lu(us)\n", (end.tv_sec*1000000+end.tv_usec)-(begin.tv_sec*1000000+begin.tv_usec));for (p = arr, last = arr+sizeof(arr); p < last; ++p)fprintf(stderr, "%c\n", *p);return 0;
}

与代码一相似,只是遍历时使用字符指针。

执行如下命令:

$ gcc -o b b.c
$ ./b 2>/dev/null

那么执行时长如何呢?取个平均一点的结果:

2972(us)
两者对比

可以看到,指针遍历的速度似乎比下标要快。但由于时差有些接近,也无法非常肯定,因此我们来看看编译生成的汇编。

#a.c生成的a.s
...movl	-4(%rbp), %eaxcltqmovb	$99, -1024016(%rbp,%rax)addl	$1, -4(%rbp)
.L2:movl	-4(%rbp), %eaxcmpl	$1023999, %eax
...
#b.c生成的b.s
...movq	-8(%rbp), %raxmovb	$99, (%rax)addq	$1, -8(%rbp)
.L2:movq	-8(%rbp), %raxcmpq	-16(%rbp), %rax
...

碍于篇幅,仅列出赋值循环中的部分的汇编代码。

可以看到,a.c(数组下标版本)生成的汇编中在给每个数组元素赋值时需要用数组首地址配合下标计算出要被赋值的单元位置。而b.c(指针版本)则不需要这一步运算。当然还有一个cltq指令的差异,该指令作用是将32位eax有符号扩展到64位。

到此,似乎汇编差异带来的性能差异符合我们刚才看到的时间度量差异。

但是,文章到此并未结束,细心的读者或许会注意到,我们刚才的编译是并未被优化的。那么下面,我们来试试编译优化的结果。

代码一的优化结果
$ gcc -o a a.c -O3
$ ./a 2>/dev/null
549(us)
代码二的优化结果
$ gcc -o b b.c -O3
$ ./b 2>/dev/null
546(us)
对比结果

首先,可以看到优化后的代码执行效率远高于优化前的。

其次,优化后,两段代码的执行时间似乎很相近。我们依旧来看看汇编代码:

#a.c经过O3优化的a.s
...leaq	32(%rsp), %rdimovl	$1024000, %edxmovl	$99, %esicall	memsetleaq	16(%rsp), %rdixorl	%esi, %esi
...
#b.c经过O3优化的b.s
...leaq	32(%rsp), %rdimovl	$1024000, %edxmovl	$99, %esicall	memsetleaq	16(%rsp), %rdixorl	%esi, %esi
...

你没看错,我也没有写错,经过优化后的代码,循环赋值部分是完全一样的。这也与我们的时间度量结果吻合。

总结

在无编译优化的情况下,数组下标的遍历方式会略慢于指针遍历,是由于数组下标方式在每次循环中需要利用数组首地址和数组下标计算出被使用的数组元素。

在O3优化情况下,编译优化带来的性能提升也是非常可观的,同时,编译优化也一定程度上缩小了遍历方式差异带来的性能差异。虽然O3优化有极个别时候会有指令乱序导致程序执行结果与预期不符的情况,但也是有相应解决方案的。



喜欢的朋友欢迎关注码哥,也可以在下方留言评论。

感谢观看!

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

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

相关文章

【QML】QML复制文件或文件夹,显示进度,多线程复制

1. 效果 可以显示复制文件和文件夹的进度 复制文件&#xff1a; bool copyFileFunc(QString _from, QString _to);复制文件夹&#xff1a;bool copyDirectoryFiles(const QString &_from, const QString &_to);举例&#xff1a; //复制文件copyhelper.copyFileToDir(&…

推荐12款好用的在线平面设计工具,让设计更简单

平面设计是图形表达和信息展示的重要手段&#xff0c;在游戏场景和角色造型、插画、广告制作等艺术设计领域有着重要的应用&#xff0c;如海报设计、包装设计等。 平面设计强调视觉传达&#xff0c;一般以图像、图形和文字等视觉元素为主要手段&#xff0c;通过排版、配色、构…

SpringBoot、Java AOP实现方式

SpringBoot、Java AOP实现方式 搭建项目环境 我这里直接使用Maven创建项目之后再pom.xml中导入包 Spring版本 如果你的版本有最新的&#xff0c;最简单的办法就是&#xff0c;将版本都换成统一的&#xff0c;因为发布时候都是每个版本统一发布的&#xff0c;如果出现不兼容的…

大模型讲座

盘古NLP大模型典型场景 千亿大模型训练难点和解决方案 训练状态不稳定&#xff08;经常训练中断等&#xff09; 解决1&#xff1a;对loss和梯度等多维状态实时监测。对数据、学习率、参数精度、模型梯度进行针对性调整和断点恢复。 调整学习率的代码如下。调整参数、梯度类似…

kali安装HTTrack报错Unable to locate package httrack

kali安装后&#xff0c;直接安装Httrack导致报错 Unable to locate package httrack &#xff08;这里因为解决了&#xff0c;无法重现&#xff0c;则使用错误的包httrackttttt&#xff09; 原因&#xff1a;安装kali后第一次使用系统&#xff0c;则应该运行update命令 sudo …

基于ssm省出口基地公共信息服务平台论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本n省出口基地公共信息服务平台就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞…

算法训练营Day19

#Java #二叉树 #双指针 开源学习资料 Feeling and experiences&#xff1a; 二叉搜索树的最小绝对差&#xff1a;力扣题目链接 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的…

eNSP小实验--实现全网互通

目录 一、建立以下拓扑图&#xff0c;并实现全网互通 二、分析 1、接入层交换机SW4、SW5划分vlan 2、汇聚层交换机SW2,SW3配置ip作为vlan网关&#xff0c;与SW1直连 3、核心交换机SW1配置ip 与汇聚层交换机和R1直连 4、SW1,SW2,SW3,R1配置静态路由&#xff0c;使得vlan10,…

算法学习——回溯算法

回溯算法 理论基础回溯法的效率回溯法解决的问题回溯法模板 组合思路回溯法三部曲 代码 组合&#xff08;优化&#xff09;组合总和III思路代码 电话号码的字母组合思路回溯法来解决n个for循环的问题回溯三部曲代码 组合总和思路代码 组合总和II思路代码 理论基础 什么是回溯法…

教师职业规划

教师是一份充满责任和使命感的职业&#xff0c;也是一个具有广泛影响力的职业。作为一名教师&#xff0c;不仅要传授知识&#xff0c;更要培养学生的品德和能力&#xff0c;为他们的未来发展奠定基础。因此&#xff0c;进行职业规划对于教师来说是非常重要的。 首先&#xff0…

VUE篇之可拖动裁剪框

涉及知识点&#xff1a; offsetLeft, offsetTop, offsetWidth, offsetHeight&#xff1b;offsetX, offsetY&#xff1b;clientX&#xff0c;clientY css:clip-path 学习直通车&#xff1a;HTMLElement.offsetLeft - Web API 接口参考 | MDN MouseEvent.offsetX - Web API 接…

利用原始套接字解决mac地址错误问题【南瑞SysKeeper-2000】

一&#xff1a;案例描述 一键可视顺控图像智能项目在网络部署过程中&#xff0c;对网络限制隔离安全性要求很高&#xff0c;用到正向隔离装置&#xff08;南瑞SysKeeper-2000型号&#xff09;。 图一 正向装置示意图 现场发现问题&#xff1a;直连网线情况下&#xff0c;我方…

德人合科技 | 公司电脑文件加密系统

公司电脑文件加密系统是一种可以对电脑文件进行加密的保护机制。它使用驱动层透明加密技术&#xff0c;能够在用户无感知的情况下对文件进行加密&#xff0c;从源头上保障数据安全和使用安全。 PC端访问地址&#xff1a; www.drhchina.com 此类系统主要有以下几个特点和功能&a…

Web前端-JavaScript(js循环)

1.循环 1.1 for循环 语法结构 for(初始化变量; 条件表达式; 操作表达式 ){//循环体 }名称作用初始化变量通常被用于初始化一个计数器&#xff0c;该表达式可以使用 var 关键字声明新的变量&#xff0c;这个变量帮我们来记录次数。条件表达式用于确定每一次循环是否能被执行。…

Git账户密码http方式的配置

Git账户密码http方式的配置 入门 git在提交时每次都需要输入密码和账号信息&#xff0c;可以将账号和密码进行持久化存储&#xff0c; 当git push的时候输入一次用户名和密码就会被记录&#xff0c; 不需要每次输入&#xff0c;提高效率&#xff0c;进行一下配置&#xff1…

深入学习《大学计算机》系列之第1章 1.4节——从二进制起源窥见的奥秘

一.欢迎来到我的酒馆 第1章 1.4节&#xff0c;从二进制起源窥见的奥秘。 目录 一.欢迎来到我的酒馆二.二进制的起源1.关于莱布尼茨2.莱布尼茨和牛顿的恩怨情仇 二.二进制的起源 本节内容属于知识拓展&#xff0c;通过讲解几个小故事&#xff0c;向大家介绍二进制的起源。 1.关…

基于低代码的文档管理系统:实现高效协作与控制

在企业和组织中&#xff0c;文档管理是一项至关重要的任务。文档包括各种类型的信息&#xff0c;如合同、报告、会议记录、产品规格等&#xff0c;它们都需要被妥善保管并确保随时可供查阅。 传统的文档管理方法往往效率低下&#xff0c;且容易出错。随着技术的发展&#xff0…

亚信安慧AntDB数据库引领大数据新纪元,星河案例彰显卓越表现

亚信科技及其附属公司亚信安慧在第六届大数据“星河”案例评选中&#xff0c;凭借其卓越的数据库技术实力&#xff0c;再次站在了行业的聚光灯下。这次的显著成果不仅是对亚信科技技术能力的肯定&#xff0c;更是对其在数据库领域持续创新和领先地位的认可。 图&#xff1a;亚信…

3D小球跑酷

目录 一、前言 二、开发环境 三、场景搭建 1. 创建项目 2. 创建场景内物体 2.1 创建跑道 2.2 创建玩家 2.3 创建障碍物 2.4 改变跑道和障碍物的颜色 2.4.1 创建材质 2.4.2 给跑道和障碍物更换材质 四、功能脚本实现 1. 创建玩家脚本 2. 相机跟随 3. 胜负的判定 3…

单光子如何“玩转”单原子?| 量子简史

在量子力学诞生约100年后的今天&#xff0c;物理学家仍在不断了解光与物质之间的相互作用。 上世纪初&#xff0c;量子力学发展的驱动力之一是人们需要了解为什么原子只能发出特定波长的光。不久之后&#xff0c;量子力学被应用于分子&#xff0c;然后是固体。从另一个方向来看…