找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2734|回复: 6
收起左侧

C语言特性,节省空间,保留可读性

[复制链接]
ID:392682 发表于 2022-4-20 17:31 | 显示全部楼层 |阅读模式
我们开发的电表,基于单片机的,电表的功能越来越多,要求我们再硬件不变的情况下增加这些功能,所以就经常会考虑程序大小问题,有时真的会按字节去省空间,因为,就是那几个字节编译就爆掉了。但是还要求尽量程序可维护性好(简单、直接、易读)。这时就要去程序中寻找能省空间的地方,能用指针就考虑要不要换指针,牺牲一些可读性,使用for&if代替switch的一些表达式。重复的语句使用函数代替,使用位域,寻找简便的程序处理方法等,,打开编译产生的map文件分析哪里占的存储大,进行精简,真是挺有意思的。就好像捉迷藏。

这些省空间的操作有些基于C语言的特性,比如指针,比如位操作,比如位域操作在保留可读性的情况下代替一堆flag。
struct file_data{
unsigned int day: 5;
unsigned int month: 4;
unsigned int year: 7;
}
struct file_data fd;
fd.day = 20;
fd.month = 4;
fd.year = 22;
这样定义,变量day占了5个位,month占4个位,year占7位。同时也保留了可读性。
虽然这种写法省空间,但是有限,而且不太好用,迫不得已还是别这么搞。但是位操作的话这么些会好看一点如:
struct bits{
unsigned int flag_0: 1;
unsigned int flag_1: 1;
unsigned int flag_2: 1;
unsigned int flag_3: 1;
unsigned int flag_4: 1;
unsigned int flag_5: 1;

unsigned int flag_6: 1;
unsigned int flag_7: 1;

};

struct bits flag_grop;
if(flag_grop.flag_0 == 1)
{
    flag_grop.flag_1 = 0;
}
这样写一些还可以。

还有联合体,在不增加开销的情况下简洁的提供了多种解析数据的方式,真是一个不错的工具
union bits{
u8 data;
unsigned int flag_0: 1;
unsigned int flag_1: 1;
unsigned int flag_2: 1;
unsigned int flag_3: 1;
unsigned int flag_4: 1;
unsigned int flag_5: 1;

unsigned int flag_6: 1;
unsigned int flag_7: 1;


};
union bits flag_grop;

flag_grop = 0xAA;

if(flag_grop.int flag_0 == 1)
{}
if(flag_grop.int flag_1 == 1)
{}
...
如上该联合体只占了一个字节的空间。提供了两种方便读写操作的解析数据的方式 字节操作与位操作。
联合体用来处理通讯挺好的。
假设串口发送数据是按字节发送,但是我们要发送的数据可能时16位的或者32位的,还会面临先发高子节还是低字节问题。1、我们可以使用指针
将一个整型数据分为4次发送。2、我们也可以利用联合体的特性将整型数据分4次发出。还能增加一点可读性。


今天看到一句话:no time to be brief 感觉有时用着还挺好

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:392682 发表于 2022-5-4 11:50 | 显示全部楼层
fj51hei 发表于 2022-4-30 15:02
就是本来没有位操作指令 你程序却写位操作语法 编译器为满足你的程序意图  只能按它自己的想法给你弄一堆 ...

这样啊,这点真没想到,当时想当然的认为,位域操作会被转化为简单常规的与或非操作了。有点惭愧哈,想当然了。可读性好点,但是对于节约空间效果可能没啥效果
回复

使用道具 举报

ID:824490 发表于 2022-4-30 15:11 | 显示全部楼层
本帖最后由 名字不是重点 于 2022-4-30 19:13 编辑

我错了

回复

使用道具 举报

ID:712493 发表于 2022-4-30 15:02 | 显示全部楼层
qinshuai 发表于 2022-4-29 16:52
没太了解,在不支持位操作的单片机上,位域操作会怎加flash的开销吗?

就是本来没有位操作指令 你程序却写位操作语法 编译器为满足你的程序意图  只能按它自己的想法给你弄一堆汇编实现了  这样下来FLASH开销就大  就如没有硬件乘除法的单片机  你却出现很多乘除法  那就不是FLASH开销大的问题  也会造成程序效率不高的问题
回复

使用道具 举报

ID:392682 发表于 2022-4-29 16:52 | 显示全部楼层
Hephaestus 发表于 2022-4-23 18:35
在不支持位操作的单片机上面,楼主的写法会严重增加代码长度,节约了ram却大大浪费了flash,得不偿失。

...

没太了解,在不支持位操作的单片机上,位域操作会怎加flash的开销吗?
回复

使用道具 举报

ID:883242 发表于 2022-4-23 18:35 | 显示全部楼层
在不支持位操作的单片机上面,楼主的写法会严重增加代码长度,节约了ram却大大浪费了flash,得不偿失。

在支持位操作的单片机上,比如51,用专门的关键字bdata、bit来操作也比楼主的写法节约了很大的空间。

所以楼主的文章,没有什么用。
回复

使用道具 举报

ID:301191 发表于 2022-4-23 18:28 | 显示全部楼层
顶一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表