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


正文


大家好,我是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++语言

☞ 专辑|经验分享

☞ 专辑|电能控制技术

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
结构体嵌套对性能产生一定的影响,但具体影响的大小取决于嵌套的深度和结构体的大小。以下是一些可能的影响: 1. 内存占用:结构体嵌套增加内存的占用,因为每个嵌套结构体都需要分配内存空间。如果结构体嵌套很深或者结构体本身很大,那么占用的内存也更多。 2. 访问效率:访问嵌套结构体成员需要多次解引用,这增加访问成员的开销。尤其是在多层嵌套的情况下,访问成员可能需要多次指针解引用操作,导致额外的性能开销。 3. 缓存效果:CPU有多级缓存,可以提高数据的读写效率。但是,如果结构体嵌套导致数据在内存中不是连续存储的,可能降低缓存的命中率,从而影响性能。 为了减少结构体嵌套对性能的影响,可以考虑以下策略: 1. 减少嵌套深度:尽量避免过深的结构体嵌套,可以将部分成员提取到外层结构体中,减少解引用操作的次数。 2. 优化结构体大小:尽量避免结构体过大,可以考虑使用数据对齐、紧凑的成员排列等技术减小结构体的内存占用。 3. 优化数据访问方式:在访问嵌套结构体成员时,可以使用指针或者引用来减少解引用操作的开销。 总之,结构体嵌套对性能产生一定的影响,但具体的影响因情况而异。在设计和使用结构体时,需要根据具体的应用场景和性能需求来权衡结构体嵌套深度和大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值