历史上的今天
返回首页

历史上的今天

今天是:2025年01月07日(星期二)

正在发生

2020年01月07日 | 浅谈链表对stm32等芯片程序中的提升作用(C语言)

2020-01-07 来源:eefocus

程序中经常面临这样的一个问题,需要创建一定数量的对象,但事前又不知道对象的具体个数,因此新手通常的做法都会为了能处理足够的对象信息,创建一个足够大的空间数组。这里举个简单的例子,某个应用要求管理学生信息,因此设置了这样的一个结构体(类似于面向对象语言里说的成员属性)


typedef struct 

{

int num;

int age;

char *name;

}studentInfo;

在不引入链表的情况下,为了能管理尽可能多的学生信息,可能会这样创建这个结构体的实体:


studentInfo student[1024*100];

int studentCnt = 0;    //记录已经管理的学生数量

这样的处理方法,理论上能实现需求,而且在学生数量还小的时候,这个程序基本也不会出现明显的问题。但这样的做法存在很多方面的问题,当一个数组被创建时,其在内存中的大小就已经被固定了,所以,1,当学生数量较小时,这个程序的处理方法浪费了大量的内存空间,特别是在资源紧缺的单片机或嵌入式系统中,这样的做法是不符合要求的。2,当学生数量大于设置的数量时(即例子中的1024*100),即使系统中还剩有内存空间可以继续添加,而这个程序也无法再添加学生信息。3,当学生数量比较大时,遇到删除信息的操作,程序的处理效率非常低,处理方法通常是,找个需要删除的信息的存放位置,然后把后面的信息逐步往前覆盖,如果删除的是最后一个,则设置为0,从而达到删除的目的。


如果引入链表,以上的三个问题都能完美解决,但需要配合内存管理才能实现,因此如果是嵌入式系统,还需要实现内存管理方面的功能,关于内存管理,将在下篇文章中提到。使用链表的方式,在原有的成员属性结构体的前提上,还要再封装多一层链表管理。以单向链表为例:


typedef struct 

{

int num;

int age;

char *name;

}studentInfo;

 

typedef struct students

{

struct students *nextStudent;    //用于指向下一个学生信息

studentInfo *Info;     //具体的信息

}studentsTypedef; 

 

studentsTypedef *headStudents; //链表的头指针

看到这里,会发现用到的基本上是指针,有些同学可能会比较害怕用指针,其实用多了就会发现,指针也就是那么回事。好了,既然是指针,那么它是没有用来存放数据的内存空间的,而链表的精髓在于,具体的数据信息是通过内存管理申请内存存放,而链表结构则负责指向各自负责管理的数据,从而实现关联。


由于在定义的时候,只定义了一个头指针,那么它也只是个指向了studentsTypedef也就是链表结构体的指针,同样没有内存空间,在没有创建新增链表之前,它是一个野指针。


所以,在具体应用之前,需要先执行一个初始化操作,也就是申请空间给链表管理结构体,然后头指针指向这个空间。


//

//初始化

//

bool studentsListInit(void)

{

    //申请链表类型大小的空间,并让头指针指向它

headStudents = (studentsTypedef*)malloc(sizeof(studentsTypedef));

if(headStudents == NULL) return false;

 

    //同时要标记下一个信息为空

headStudents->nextStudent = NULL;

return true;

}

这里使用了一个malloc函数,作用是申请内存,在PC端编写测试程序时可以使用这个函数,需要包含的头文件时malloc.h。如果是在嵌入式系统中,直接使用malloc会导致一些内存碎片的问题,比较多的做法是自己实现一定的内存管理方法,包括申请内存,释放内存,高端的内存管理方法还会包含碎片整理的功能。如果是使用类似FreeRTOS这样的操作系统,RTOS中已经为我们提供了几种内存管理的方法,使用较广泛的heap4。


需要新增一个学生信息,实现方法可以这样写:


bool AddStudentToList(studentInfo *stuInfo)

{

    //在链表的最后加入

studentsTypedef *p = headStudents;

while(p->nextStudent!=NULL)

{

p = p->nextStudent;

}

    

    //先申请链表结构体的空间,因为后续还要继续增加

p->nextStudent =  (studentsTypedef*)malloc(sizeof(studentsTypedef));

if(p->nextStudent == NULL) return false;

    

    //指向刚刚申请的空间,并为需要存放的学生信息申请对应的内存

p = p->nextStudent;

p->Info = (studentInfo*)malloc(sizeof(studentInfo));

if(p->Info == NULL) 

    {

        free(p);//由于申请失败,先前申请的链表空间也要释放

        return false;

    }    

 

    //具体信息赋值

memcpy(p->Info,stuInfo,sizeof(studentInfo));

 

    //标记这个链表的尾部

p->nextStudent=NULL;

 

    //添加成功

return true;

}


到这里可以发现,当需要添加一个学生的管理信息时,这里的程序就相应的申请一个学生信息所需要的空间,这样一来,可以实现内存的利用最大化,不会出现申请了内存但不使用的情况。到这里已经解决了上面说到的2个问题。


下面再来看删除操作:


bool deleteStudentInfo_AccordingNum(int num)

{

bool res = false;

studentsTypedef *p =  headStudents;

while(p->nextStudent!=NULL)

{

studentsTypedef *temp = p;

p = p->nextStudent;

if(p->Info->num == num)

{

temp->nextStudent = p->nextStudent;

//释放内存空间 

free(p->Info);

free(p);

p=temp;

res = true;

}

}

return res;

}

可以看到,删除一个节点,只需要找到该节点的位置,至于怎么找这个节点,可以根据不同的方法,我这里只是随便举个例子。找到之后,只需要改变一下原来链表结构的指向,并释放被删除节点所占用的内存空间,整个删除操作就完成了,不需要像数组那样,找到之后,还要把后面的节点逐个往前面移动,效率非常低。当然,链表也并不是完全优于数组的,链表的访问只能从头节点开始,而数组的访问,可以直接使用下标,结合一定的算法,如二分排序法等,使用数组的方法的查找效率就高于链表的方法,具体如何选择,需要看实际的应用场景。


最后再贴上main函数中,测试的部分。


void printfStudentInfo(void)

{

printf(" list      num age namern");

studentsTypedef *p = headStudents;

int i=0;

while(p->nextStudent!=NULL)

{

p = p->nextStudent;

printf("  %d %d %d %srn",i,p->Info->num,p->Info->age,p->Info->name);

i++;

}

printf("----------------------------end--------------------rn");

 

 

int main(int argc,char *argv[])

{

printf("-------------List test---------------rn"); 

if(!studentsListInit( ))

{

printf("Memory fail..rn");

}

 

studentInfo temp;

for(int i=0;i<5;i++)

{

temp.age = 20+i;

temp.num = i;

temp.name = (char*)"A";

if(!AddStudentToList(&temp))

{

printf("Add student %d info failrn",i);

}

}

printfStudentInfo();

deleteStudentInfo_AccordingNum(4);

printfStudentInfo();

 

temp.age = 18;

temp.num = 1001;

temp.name = (char*)"TEST";

if(!AddStudentToList(&temp))

{

printf("Add student %d info failrn",1001);

}

printfStudentInfo();

}

推荐阅读

史海拾趣

Amphenol Piher公司的发展小趣事

Amphenol Piher 是 Amphenol 公司的一部分,专注于设计、制造和销售电子行业中的传感器和电位器等产品。以下是关于 Amphenol Piher 公司发展的五个相关故事:

  1. 创立与初期发展:Amphenol Piher 公司的历史可以追溯到20世纪60年代,在西班牙的Valencia成立。最初,公司主要致力于生产电位器和传感器等电子元器件,为不同行业的客户提供定制化的解决方案。随着市场需求的增长和公司技术实力的提升,Amphenol Piher 逐渐赢得了客户的信任和市场认可。

  2. 技术创新与产品多样化:Amphenol Piher 公司在技术研发方面持续投入,并不断推出新型的传感器和电位器产品。公司专注于提升产品性能、精度和可靠性,满足客户对高品质电子元器件的需求。除了传统的电位器和传感器,Amphenol Piher 还推出了一系列新型产品,如角位移传感器、线性位移传感器等,为不同应用领域提供多样化的解决方案。

  3. 客户合作与定制化解决方案:Amphenol Piher 公司与客户建立了紧密的合作关系,致力于开发定制化的传感器和电位器解决方案。公司的工程团队与客户密切合作,根据客户的需求和应用场景,设计和制造符合特定要求的产品。这种定制化解决方案能够满足客户个性化的需求,为客户提供更加专业和完善的服务。

  4. 质量控制与认证标准:Amphenol Piher 公司高度重视产品质量控制,并严格遵循国际质量管理体系标准。公司的生产工艺和质量管理体系符合ISO 9001质量管理体系认证标准,以确保产品质量的稳定性和可靠性。此外,Amphenol Piher 公司的产品还通过了各种行业和应用领域的认证标准,如汽车行业的TS16949认证等,确保产品符合行业标准和规定。

  5. 全球市场拓展与合作伙伴关系:除了在西班牙的生产基地外,Amphenol Piher 公司还在全球范围内设有多个销售办事处和代理商网络,拓展了国际市场份额。公司与全球各种行业领先企业建立了长期稳定的合作关系,共同推动产品的创新和市场拓展。通过全球市场拓展和合作伙伴关系,Amphenol Piher 公司不断扩大业务规模,增强了在电子行业中的市场竞争力。

这些故事展示了 Amphenol Piher 公司从成立初期到如今在技术创新、产品多样化、客户合作与定制化解决方案、质量控制与认证标准以及全球市场拓展与合作伙伴关系等方面取得的重要进展。

台湾岱恩(DAIN)公司的发展小趣事

以下是关于台湾岱恩(DAIN)电子工业股份有限公司在电子行业中发展起来的五个相关故事,每个故事都基于事实进行描述,避免主观褒贬:

  1. 创业初期的专注与坚持

岱恩电子工业股份有限公司成立于1989年,初期专注于薄膜电容器的研发与生产。公司凭借对技术的深入研究和对品质的严格把控,迅速在薄膜电容器领域崭露头角。在创业初期,岱恩电子就明确了以技术创新和品质保证为核心竞争力的战略定位,为公司的长远发展奠定了坚实的基础。

  1. 品质管理的建立与提升

岱恩电子始终将品质管理作为企业发展的重中之重。自成立之初,公司就引进了ISO9001国际品质认证体系,并在随后的几年中不断完善和提升。通过严格的质量控制流程和持续的品质改进活动,岱恩电子的产品品质得到了客户的广泛认可,并在市场上建立了良好的口碑。

  1. 环保理念的贯彻与实践

随着全球环保意识的不断提高,岱恩电子积极响应环保号召,将环保理念贯穿于企业发展的全过程。公司不仅取得了ISO14001环境管理系统认证,还严格遵守RoHS及Reach等欧盟环保标准,确保产品从原材料采购到生产过程的环保性。此外,岱恩电子还积极推广绿色制造技术,努力降低生产过程中的能源消耗和废弃物排放。

  1. 产品创新的突破与引领

在薄膜电容器领域,岱恩电子一直致力于产品创新和技术突破。公司不断投入研发资源,推出了一系列具有高性能、高可靠性和长寿命特点的薄膜电容器产品。其中,X2电容作为公司的明星产品之一,凭借其优异的电气性能和稳定性,赢得了众多客户的青睐。同时,岱恩电子还积极拓展产品线,将业务范围扩展至发光二极体等领域,进一步提升了公司的市场竞争力。

  1. 全球市场的拓展与布局

为了更好地服务全球客户,岱恩电子在中国大陆和台湾设立了完整的销售体系,并积极拓展海外市场。公司通过与全球知名企业的合作与交流,不断提升自身的品牌影响力和市场占有率。同时,岱恩电子还注重本地化服务,根据不同地区的市场需求和文化特点,提供定制化的产品和服务解决方案,赢得了客户的信任和赞誉。

普芯达电子(Chipswinner)公司的发展小趣事

在电子行业中,技术创新是企业持续发展的关键。普芯达电子深知这一点,因此始终将技术创新作为公司发展的核心驱动力。公司不断加大研发投入,引进先进技术和设备,培养了一支高素质的研发团队。通过持续的技术创新和产品升级,普芯达电子不断推出具有市场竞争力的新产品,为客户提供了更加优质和多样化的选择。

Electronic公司的发展小趣事

AMD,曾经一度陷入困境的半导体公司,近年来实现了逆袭。AMD通过持续的技术创新和市场竞争策略的调整,成功在处理器和显卡市场取得了重要份额。AMD的产品性能不断提升,价格也更加亲民,赢得了消费者的广泛认可。同时,AMD还积极与游戏厂商和硬件厂商合作,推出了多款定制化的产品和解决方案。这些努力使得AMD在激烈的市场竞争中逐渐崭露头角。

Frequency Management International公司的发展小趣事

作为一家有社会责任感的企业,FMI深知可持续发展和环保的重要性。公司积极响应国家环保政策,采用环保材料和生产工艺,减少对环境的影响。同时,FMI还致力于节能减排和资源循环利用等方面的研究和实践工作。这些努力不仅体现了FMI对环境保护的承诺和责任感,也为公司的长期发展奠定了坚实的基础。

综上所述,Frequency Management International公司凭借其创立与早期发展、技术创新与产品线拓展、市场拓展与国际化战略、质量管理与客户服务以及可持续发展与环保责任等方面的努力和发展历程,在电子行业中取得了显著的成就和地位。

聚辰(Giantec)公司的发展小趣事

自1994年(部分资料显示为1993年,但此处采用最新信息)成立以来,港源公司始终将技术创新视为企业发展的核心驱动力。公司专注于轻触开关、微动开关、AC/DC插座、变压器等开关零组件产品的研发,通过引进国内外先进技术,并自主成功研发了自动化生产设备和检测设备,实现了生产自动化,大幅提升了产品质量和生产效率。港源公司还积极参与国际技术交流与合作,与众多行业标杆客户长期紧密合作,能够尽早了解市场需求,快速响应并推出符合行业标准的新产品,从而引领了电子开关行业的发展方向。

问答坊 | AI 解惑

中嵌联盟“百家e坛”嵌入式技术主题论坛第二期火爆召开

  本月6日下午,中嵌联盟“百家e坛”嵌入式技术主题论坛第二期于中关村软件园港湾大厦举办。虽然正值北京残奥会即将开幕的举国欢庆之际,但本次活动仍然吸引了包括工程师、教授、在校大学生在内的60多位嵌入式技术爱好者的热情参与。 &n ...…

查看全部问答>

十说电容经典

话说电容之一:电容的作用 作为无源元件之一的电容,其作用不外乎以下几种:1、应用于电源电路,实现旁路、去藕、滤波和储能的作用。下面分类详述之:1)旁路旁路电容是为本地器件提供能量的储能器件,它能使稳压器的输出均匀化,降低负载需 ...…

查看全部问答>

51单片机用定时写流水

初学单片机中断定时感觉什么也不懂,哪位能帮我写个用定时的流水灯!(要用汇编写)…

查看全部问答>

IImage接口下如何取得或變更特定點pixel值

如題 小弟是這方面的新手 參考論壇內文章後可以成功利用IImage接口顯示圖片至PPC螢幕上 目前不知如何取得與改變IImage格式下的任意位置的PIXEL值 (類似GETPIXEL()和SETPIXEL()的功能) MSDN查了很久IMAGING.H沒有上述兩個功能 不知道有沒有人能 ...…

查看全部问答>

True Connect软件可以通过PC在Windows Mobile手机下显示和操作鼠标,它是如何实现的?

我想在Windows Mobile手机中实现鼠标,包括显示、左键和右键。可WinCE却不支持鼠标显示,有的话也只是个忙的沙漏鼠标,有什么方法显示鼠标呢? 我下了软件True Connect,WM5手机通过USB与PC连接后,TrueConnect可在手机中显示和操作鼠标,说明手机 ...…

查看全部问答>

STR710的警报中断标志一直为1?!

                                 开放RTC的通用中断和秒中断后,可以正常产生中断,但是一旦使能警报中断,这里警报中断时间比秒中断时间长的多,但 ...…

查看全部问答>

ISP下载器问题

现在帮老师做USBASP下载器,用mega8做,TQFP封装,电路图网上找的,就是不知道现在最新电路图是什么样的,还有,最重要的是程序啊,兄弟们快来帮帮忙,最好将电路图和程序一同附上。 还有一个问题,下载器是把m8焊上去再烧程序吧?那怎么烧进去呢…

查看全部问答>

深入浅出玩转FPGA—全部verilog程序 特权同学

深入浅出玩转FPGA—全部verilog程序 特权同学…

查看全部问答>

我的易电源整理贴

易电源试用就要结束了。我根据周计划做了以下试用。在这里规整一下。昨天收到易电源套装上照片 https://bbs.eeworld.com.cn/thread-341057-1-4.html 易电源电源模块试用心得 https://bbs.eeworld.com.cn/thread-341724-1-3.html易电源WEBENCH学习心 ...…

查看全部问答>

刚做的5438学习板,大家给点意见

刚做的5438学习板,大家给点意见哈!~程序和文档资料还在不断完善中!!! [ 本帖最后由 OURJCDZ 于 2012-11-20 22:29 编辑 ]…

查看全部问答>