【典藏】大佬们都在用的结构体进阶小技巧

发表于 4年以前  | 总阅读数:516 次

1、来聊聊(轻松一刻)

今天跟大家分享一首华晨宇的《我管你》,个人觉得这首歌表达了一种年轻人的热血感,每次听都让自己非常来劲。最近工作挺忙的,写文章或许已经成为了一种兴趣和爱好了吧,也希望每次作者的唠叨都能带给各位小伙伴一些小小的收获。

2、奇妙的"结构体"

今天讲解这块内容,主要是受上篇文章结构体内部对齐的影响,来重新为大家介绍一下结构体(如果小伙伴对结构体的基础知识还不具备的话得回头看一下相关C语言的书籍).

结构体:字面上的意思就是有着层次结构的一种数据形式,所谓的层次结构就是我们在结构体中定义的各种成员了,再白话一点:结构体就是一个数据包,里面可以包含各种各样的数据。对于这句话我们还要深入挖掘一下"各种各样的数据”,对于我们编程而言-“一切皆是数据”。进一步理解,结构体里面可以包括整个程序中你想包含的东西。如果这样的推敲没错的话,那结构体还真有点东西了,作者画个图供大家揣摩,结构体的奇妙之处全在图里面了!

3、结构体"硬核"技巧

对于结构体的应用太多了,今天这篇文章我主要为大家总结平时关于结构体的一些独特小技巧,对于结构体更多优秀的编程表现,只能作者后续总结归纳以后分享给大家。好,下面进入这些有用的技巧:

1)结构体初始化有讲究

我们大部分初学的小伙伴可能都不怎么会跟结构体变量直接进行初始化,(哈哈,可能很多小伙伴定了了变量根本就不会进行初始化)不过还是要养成比较好的编程习惯,虽然现在大部分集成开发环境都会为大家把一些全局变量初始化为0,不过对于代码的可移植性、可预知性考虑还是建议既然定义了就要给一个初始状态。

好了,先上代码:

 1#include <stdio.h>
 2//结构体定义
 3typedef struct __tag_Test
 4{
 5    int param1;
 6    int param2;
 7}stTest;
 8//结构体初始化方式1
 9stTest sTest1 = {
10    .param1 = 1,
11    .param2 = 2
12};
13//结构体初始化方式2
14stTest sTest2 = {
15  1,2
16};
17/*********************************************
18 * Fuction: main
19 * Author : (公众号:最后一个bug)
20 ********************************************/
21int main(void) { 
22
23    printf("sTest1.param1 = %d\n",sTest1.param1);
24    printf("sTest1.param2 = %d\n",sTest1.param2);
25    printf("sTest2.param1 = %d\n",sTest2.param1);
26    printf("sTest2.param2 = %d\n",sTest2.param2);
27    return 0;
28}

解析一下:上面是一个非常简单的代码,其中第一种结构体的初始化是linux源码中非常常见的一种方式,这种初始化的方式编译器必须要遵循ISO C99标准,否则只能使用第二种比较常规的方式,不过现在大部分编译器都支持该标准所以也被比较普遍的使用,其带来的好处有几点:1)对于结构体成员变量的初始化更加清晰,特别是当结构体特别大的时候;2)不用在乎初始化的顺序,只需要名字和数据对应上即可,非常的灵活。

2)给同个结构体取多个名字

当你进行C编程时间久了以后,对于所属性一致的变量等你都会用结构体进行封装,那么可能出现同一个结构体可能多个地方使用的情况,并且结构体的作用会有所不同,就好像一个人他可能是一名学生,也有可能在外面兼职做一名服务员等等,如果这个人不换一身衣服或者做个标记什么的可能有时候我们难以分辨,那么在C程序里面我们会怎样为他们换个衣服呢?简单代码如下:

1#include <stdio.h>
 2
 3 struct __tag_Man
 4{
 5    int Age;
 6    int Height;
 7};
 8
 9typedef struct __tag_Man stStudent;
10typedef struct __tag_Man stWaiter;
11
12stStudent sStudent = {
13  .Age    = 12,
14  .Height = 20,
15};
16
17stWaiter sWaiter = {
18  .Age    = 12,
19  .Height = 20,
20};
21
22int main(void) { 
23
24    printf("sStudent.Age    = %d\n",sStudent.Age);
25    printf("sStudent.Height = %d\n",sStudent.Height);
26    printf("sWaiter.Age     = %d\n",sWaiter.Age);
27    printf("sWaiter.Height  = %d\n",sWaiter.Height);
28    printf("公众号:最后一个bug");
29    return 0;
30}

解析一下:上面的代码确实挺简单的,可能有些小伙伴一眼就可以看懂,不过这种使用方法时非常有价值的,特别是以后大家玩算法,比如说:节点都是一样的,不过节点分为子节点和父节点,对于一些处理函数传入的参数虽然是一样的,不过意义却不同,我们就可以通过这样的方式进行处理,从而增加代码可读性。

3)0地址与结构体的妙用

这一块的内容算是这篇文章的重点内容,各位小伙伴们要做好笔记了,作者一直非常强调一点的是多读读大佬们的代码,并且善于总结一些常用的小技巧供大家平时使用,这不我们今天就拿Linux的kernal中的两个宏定义来分享几个结构体小技巧:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 
#define container_of(ptr, type, member) ({ \
         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
         (type *)( (char *)__mptr - offsetof(type,member) );})

解析一下:

1)第一个宏定义的功能是获得一个结构体成员距离结构体首地址的偏移量,参数TYPE : 结构体类型;参数MEMBER : 结构体成员,其实这个算是比较简单的,把0地址强制类型转化为结构体类型指针,然后通过结构体指向成员即可获得结构体成员变量,然后通过&进行取地址便获得了结构体成员地址,成员的偏移 = (结构体成员地址 - 结构体首地址);然而结构体首地址为0,这样成员的偏移 = 结构体成员地址,应该足够清楚了吧。

2)第二个宏定义的功能是通过结构体成员变量获得对应的结构体首地址(也就是结构体地址),参数ptr :结构体成员变量地址;参数type : 结构体类型;参数member :结构体成员,这个宏定义可能对于一些小伙伴而言在写法上有一点点难度,不过其主要分两部分,第一部分通过typeof获得成员的类型并定义了一个const指针,定义为const的目的是不让用户对0地址的内容进行写操作,对于大部分芯片对不合法区域进行读写会引起异常。第二部分通过使用offsetof宏定义获得结构体成员相对结构体首地址的偏移,这样一相减便获得了当前结构体成员所属结构体的地址,原理公式:(结构体地址 = 结构体成员地址 - 结构体成员的偏移)。

3)这里大体说一下注意事项 : 在第二点我们谈到了typeof关键字,该关键字是GUN C标准中扩展的关键字,所以在使用该宏定义的时候需要注意一下,不然采用其他标准进行编译可能会报错。

4)最后帮助大家理解的小程序

作者要说的全在代码里面了:

#include <stdio.h> 

/**********************************
 * Fuction : from Linux Kernal 
 **********************************/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 
#define container_of(ptr, type, member) ({ \
               const typeof( ((type *)0)->member ) *__mptr = (ptr); \
               (type *)( (char *)__mptr - offsetof(type,member) );})

/**********************************
 * Fuction : 结构体定义区
 * Author  : (公众号:最后一个bug)
 **********************************/
typedef struct _tag_Test{ 
    int Member1; 
    int Member2; 
    int Member3; 
}STest;

int main(void) { 
    int iTest = 0;
    STest stTest;

    printf("offsetof(STest , Member3) : %d\n",offsetof(STest , Member3));  
    printf("&stTest                   : 0X%X\n",&stTest);    
    printf("&(stTest.Member3)         : 0X%X\n",&(stTest.Member3));  
    printf("container of Member3      : 0X%X\n",container_of(&(stTest.Member3),STest,Member3));

    //这里主要是进一步让大家理解第二个宏
    //且右侧必须加()
    iTest = ({int Val = 5; Val;});

    printf("iTest = %d\n",iTest);
    printf("欢迎关注公众号:最后一个bug\n");
    return 1; 
}

程序运行的结果如下:

offsetof(STest , Member3) : 8
&stTest                   : 0X452469E0
&(stTest.Member3)         : 0X452469E8
container of Member3      : 0X452469E0
iTest = 5

4、最后小结

今天的小知识就为大家分享到这来了,里面还有很多作者没讲得特别全面的小知识,大家看完文章以后记得都查阅一下不懂的知识,如果实在不理解也可以联系作者进行交流,不过最近作者也是特别的忙,不然也不会这么久才更一篇文章,不过还是希望各位一直支持作者,作者也会尽最大的努力为大家带来实用高效的嵌入式知识。

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录