单片机开发之节省内存大法(C语言版本)

首先聊一聊

大家都知道进行单片机编程和计算机编程有个最大的差别就是单片机的资源非常的有限,并且对于大部分低端单片机而言都没有操作系统。除了一些嵌入式级的芯片用了Linux系统外,其他大部分操作都是比较简单的RTOS,可能还有一些简单的应用或者芯片根本不用系统,直接是裸机程序。

不过大部分单片机编程都与硬件密切的结合,这样工程师能够对当前的项目对象有更多的把控能力和理解能力。但是由于它的简单,我们平时在工作中往往需要控制一个项目的成本,对于单片机的选型和资源的评估都是非常谨慎;同样随着我们项目功能的不断扩展,也会让系统程序逐步变得庞大,这时候资源的使用就更需要节约点用了。

所以当资源受限制(一般的单片机RAM也就Kb级别),比如说单片机RAM不够了,即使你有再牛的算法可能也无法加入到项目中来,那么有些同志们会问,那换芯片不就可以了吗?我只想说这位同志你想多了,对于不怎么热卖产品或者不规范的公司可能还允许你试一试,可是一般的公司项目卡着走的,换了主控芯片,暂且不说软件上的移植工作,换了芯片成本上必定增加,产品的测试都得重新规划,老板领导可不愿意了。

那么主控芯片换不了我们还有什么办法呢?那我们应该从原本的程序中挤出资源来使用了,下面我总结了几种常总方法供大家参考。(具体内容可以网络查找)

共联体-union

union-共联体,是C语言常用得关键字。从字面上的意思就是共同联合在一起的意思,union所有的成员共同维护一段能够内存空间,其内存的大小取决于所有成员中占用空间最大的成员。

union结构体由于是共用同一片内存可以大大节省内存空间,那一般什么情况下使用union?又或者union还有什么特点?下面我将用几点为大家解答。

1)所有的union的成员及本身的地址是一样的。

2)union的存储模型受大小端的影响,我们可以通过下面的代码进行测试。(如果输出结果为1,表示小端模式,否则为大端模式)

大小端小知识

大端模式(Big_endian):一个数据的高字节存储在低地址,低字节存储在高地址。其指针指向的首地址位于低地址。

小端模式(Little_endian):一个数据的高字节存储在高地址,低字节存储在低地址。其指针指向的首地址位于高地址。

3)union不同于结构体struct,union对成员的改变可能会影响到其他成员变量,所以我们要形成一种互斥使用,比如说我们的顺序执行其实就是每个代码都是互斥的,所以我们可以用union进行函数处理缓存等。(个人觉得也可以认为是分时复用,并且是不会受内存初值影响的处理)

#include<stdio.h>

typedef union _tag_test
{
  char a;
  int  b;
}uTest;

uTest test;
unsigned char Checktype(void);

int main(void)
{
    printf('%x\n',(unsigned int)&test.a);
    printf('%x\n',(unsigned int)&test.b);
    printf('%x\n',(unsigned int)&test);
    printf('%d\n',Checktype());
}
unsigned char Checktype(void)
{
     uTest chk;
     chk.b = 0x01;
     if(chk.a == 0x01)return 1;
     return 0;
}

位域

位域可能对于初学者用得比较少,不过对于大部分参加工作的工程师应该屡见不鲜了,确实它也是我们省内存的神器。

因为在我们平时编程过程中,我们使用的变量与实际情况是息息相关的,就比如说开关的状态,我们一般就是0或者是1分别表示打开和关闭,那么我们用一个bit就能表示,假如说我们用一个char来存储就几乎浪费了7个bit,如果以后也有类似的的情况,那么大部分内存都得不到有效的应用。所以C语言的位域就是用来解决这个问题。

不过我们需要注意如下几点:

1)位域是在结构体中实现的,其中位域规定的长度不能超过所定义类型,且一个位域只能定义在同一个存储单元中。

2)无名位域的使用,可以看下面的代码。

3)由于位域与数据类型有关系,那么他的内存占用情况也与平台的位数相关。(相关内容可网络查找)

#include<stdio.h>//结果:编译通过//原因:常规形式(结构体占用两个字节)typedef struct _tag_test1{  char a:1;  char b:1;  char c:1;  char d:6;}sTest1;//结果:编译无法通过//原因:d的位域长度10超过了char类型长度/*typedef struct _tag_test2{  char a:1;  char b:1;  char c:1;  char d:10;}sTest2;*///结果:编译可通过//原因:下面使用无名位域,且占8个字节typedef struct _tag_test3{  int a:1;  int b:1;  int :0;//无名位域  int c:1;}sTest3;

授权转载自公众号:“最后一个bug”,作者:未知bug

(0)

相关推荐

  • (7条消息) 结构体struct和联合体union最全讲解

    摘要:首先感谢三位博主,并做出总结. 首先了解一下struct的储存结构: 一.结构体的访问 1.结构体成员的的直接访问,如下结构体: struct  A{ int a; long *b; char ...

  • (7条消息) C语言

    C语言结构体对齐步骤: 结构体各成员对齐. 结构体总体对齐 C语言结构体对齐规则: 结构体(struct)的数据成员,第一个数据成员存放的地址为结构体变量偏移量为0的地址处. 其他结构体成员自身对齐时 ...

  • C语言知识总结——宏,枚举,结构体,共用体

    C语言知识总结——宏,枚举,结构体,共用体

  • 关闭微信5个开关,清理垃圾节省内存,手机不再卡顿使用更流畅!

    关闭微信5个开关,清理垃圾节省内存,手机不再卡顿使用更流畅!

  • 航顺单片机开发环境

    航顺单片机开发环境

  • 单片机开发板哪个好

    描述 单片机开发板是什么 单片机技术的发展以微处理器(MPU)技术及超大规模集成电路技术的发展为先导,以广泛的应用领域拉动,表现出较微处理器更具个性的发展趋势. 单片机开发板有什么用 1.可以作为烧写 ...

  • 单片机编程用什么软件?单片机开发软件有哪些?

    单片机编程需要的软件其实不多,网上看了很一大堆,什么protues仿真.Labview.Pycharm等等,其实完全没必要一下装这么多. 我从事开发这么多年真正用到最多的基本就4个. 1. Keil编 ...

  • 单片机开发中,传感器的数据处理算法

        在传感器使用中,我们常常需要对传感器数据进行各种整理,让应用获得更好的效果,以下介绍几种常用的简单处理方法: 加权平滑:平滑和均衡传感器数据,减小偶然数据突变的影响. 抽取突变:去除静态和缓慢 ...

  • 单片机开发中为什么要用RTOS?

    很多STM32单片机初学者都是从裸机开始的,裸机确实也能开发出好的产品.但是,作为一个嵌入式软件工程师,况且用的并不是51那种低端单片机,如果只会用裸机开发产品,那肯定是不够的. 要从裸机的思维转变到 ...

  • 嵌入式开发难于单片机开发?

    单片机和嵌入式,其实没有什么标准的定义来区分他们,对于进行过单片机和嵌入式开发的开发者来说,都有他们自己的定义,接下来,就谈谈本人对这两个概念的理解和感悟. 首先明确概念,什么是单片机,单片机是一种集 ...

  • 单片机开发:什么是单片机的中断?

    在学习单片机开发的过程中,中断的概念对于内置控制是必不可少的.例如,如果不使用中断来检测不规则输入的外部信号或USART通信中的接收完成等通知,则必须始终定期检查信号输入和功能结束通知. 我们可以用一 ...

  • 单片机开发:什么是单片机的串行通讯?

    单片机(MCU)具有串行通信功能,其中的数据按直线排列并按顺序传输,而并行通信则通过多个终端一次传输8位数据.与字符串"ABC"通信时,在并行通信中,每个字符同时传输,而在串行通信 ...