IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 结构体嵌套多层会不会导致效率降低? -> 正文阅读

[嵌入式]结构体嵌套多层会不会导致效率降低?


正文


大家好,我是bug菌!

之前bug菌有发布一篇不建议大家把什么东西都往结构体塞<不要什么变量都想往"结构体"里塞~>的文章,主要的观点其实是让大家能够理性的组织自己的数据结构,不要面向结构体编程,很多朋友都在后台留言发表了自己的一些看法,而主要是关于其结构体成员嵌套会不会影响程序执行效率等,观点主要是两个方面:

1)不同平台对结构体和全局变量的访问不同;

2)编译器优化能够对这些数据访问轻轻松松的优化;

其实把结构体嵌套多层这样的话题跟"干掉if_else"等等都是类似的,对于大部分开发人员和普通项目基本上是不怎么关心的,因为所选择的MCU等等性能上都能够完全覆盖。

而只有当你正在为了一些函数、中断等等的执行时间太长而发愁的时候,这些东西或许才会吸引你,此时此刻你的思考方向展现着你真正的技术水平。

其实bug菌经常会在文章中表达自己的一些思维观点,比如“时间换空间、空间换时间”;“具体情况具体分析”;"一切没有前提条件的结论都是耍流氓"等等,所以没有永恒的真理,只有相对的可行,关键还是要有一个思考和研究的过程。

1

不同平台问题

不同架构的CPU,都会有自己的一些特色,从编程语言这个层面大部分工程师基本上只会研究到指令,对应着就是不同的指令集,而程序里对变量的访问基本上就是对内存的访问,而访问的方式不同又引出来一堆寻址方式,常见的就是立即数寻址、直接寻址、间接寻址等等,寻址速度上来说一般 情况:?立即数寻址>直接寻址>间接寻址。

编译器会把C程序转化为最终的汇编指令,而C程序与汇编指令并不是一一对应的关系,很好理解 : 汇编语言也一门编程语言,在编程语言的层面他们是级别;实现同样一个功能有非常多的编码处理方式,而不同的处理方式又会带来不同的效果,所以C编译器都会有一些优化选项给用户来选择,从而满足大家的需求,这也是目前编译器开发人员努力的方向。

而对于部分C代码编译最终还是达不到执行的要求,就只能老老实实自己来编写汇编程序了。

而对于结构体的成员访问如果能够直接确定其偏移地址,编译器一般会以直接寻址的方式访问;而对于运行时才能确定其地址,则一般通过结构体的基地址间接找到结构体成员,即“基地址+偏移”的方式,所以说不管结构体嵌套多少层,不会随着嵌套层数的增加而成比例的增加访问时间。

如下是在devC++,进行O0-编译结果:

参考代码:

 1#include?<stdio.h>
 2#include?<stdlib.h>
 3
 4typedef?struct?_tag_Obj{
 5????int?var;
 6
 7????struct?_tag_member1{
 8????????int?var;
 9
10????????struct?_tag_member2{
11????????????int?var;
12
13????????????struct?_tag_member3{
14????????????????int?var;
15
16????????????????struct?_tag_member4{
17????????????????????int?var;
18
19????????????????}member4;
20
21????????????}member3;
22
23????????}member2;
24
25????}member1;
26}stObj;
27
28stObj?obj1;
29
30
31int?main(int?argc,?char?*argv[])?{
32????int?index?=?0;
33????int?a??=?0;
34
35????a?=?obj1.member1.var;
36????a?=?obj1.member1.member2.member3.member4.var;
37
38????return?0;
39}

汇编:

从汇编可以看出,这种形式的结构体,不管结构体成员嵌套多少层,其访问的结构体成员都采用直接寻址的方式。

参考代码:

 1#include?<stdio.h>
 2#include?<stdlib.h>
 3
 4typedef?struct?_tag_Obj{
 5????int?var;
 6
 7????struct?_tag_member1{
 8????????int?var;
 9
10????????struct?_tag_member2{
11????????????int?var;
12
13????????????struct?_tag_member3{
14????????????????int?var;
15
16????????????????struct?_tag_member4{
17????????????????????int?var;
18
19????????????????}member4;
20
21????????????}member3;
22
23????????}member2;
24
25????}member1;
26}stObj;
27
28#define?MAX_NUM?5
29stObj?obj[MAX_NUM];
30
31
32
33int?main(int?argc,?char?*argv[])?{
34????int?index?=?0;
35????int?a??=?0;
36
37????a?=?obj[index].member1.var;
38????a?=?obj[index].member1.member2.member3.member4.var;
39
40????return?0;
41}

对于这种嵌套有数组的结构体,且访问数组内成员,需要在运行时根据index变量来最终确定成员的地址,同样我们来看看汇编:

这里首先获得index变量,然后计算出结构体成员的偏移进行访问,这里采用了一种间接寻址的方式,相比前面的小例子增加了很多指令,运行也必然要更耗时,如果每一层嵌套均需要索引,那么耗时可想而知,处理办法我在前面的文章有提及,这里就不在多说了~

2

试着调高优化等级

经常有朋友问我要不要开启优化,其实不开启优化的话,大部分C代码都是按照编写者逻辑几乎一对一的"翻译",所以打开C代码和汇编代码也可以按照逻辑对应上,当然一些实在是太无脑的C代码,即使不开优化等级,编译器也是会处理的。

所以在没有开启优化的情况下,编译器把更多的逻辑和优化处理交给C程序员,而一旦你开启了优化等级,那么编译器会自主的根据一些优化规则来对编译过程进行调整,此时进行C与汇编的对照就会有所差异。

下面我们把Dev的编译等级提升为High,然后对程序进行相应的修改,不然前面的程序直接被优化掉,灰都不剩~。

参考代码:

1int?main(int?argc,?char?*argv[])?{
2????int?index?=?0;
3????int?a??=?0;
4
5????scanf("?%d",&index);?
6????a?=?obj[index].member1.member2.member3.member4.var;
7????printf("?a?=?%d\n",a);?
8????return?0;
9}

通过获得index的值,然后索引相应的结构体成员,相应的汇编如下:

从汇编可以看出其也是分为两步,获得index,然后通过间接寻址获得最终的结构体成员,不过相比之前没有优化要短小精悍很多。

所以对于做算法的伙计们,优化代码和算法的执行效率, 优化等级是需要好好研究的,而对于所在平台优化情况不是特别熟悉的朋友,还是先研究好会优化什么内容,然后再开启优化选项等级和选项,以免造成运行异常。

好了,具体情况再具体分析吧~

最后

? ? 今天的内容就到这里了,觉得有所收获,记得点个哦~~

推荐专辑??点击蓝色字体即可跳转

???MCU进阶专辑?

???嵌入式C语言进阶专辑?

???“bug说”专辑?

??专辑|Linux应用程序编程大全

??专辑|学点网络知识

??专辑|手撕C语言

??专辑|手撕C++语言

??专辑|经验分享

??专辑|电能控制技术

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 23:07:51  更:2021-07-14 23:08:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 14:04:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码