如何提高单片机C语言代码效率
代码效率包括两个方面内容:代码的大小和代码执行速度。如果代码精简和执行速度快,我们就说这个代码效率高。一般情况下,代码精简了速度也相应提上来了。单片机的ROM和RAM的空间都很有限,当您编程时遇到单片机的ROM和RAM的不够用的时候,或者您的程序要求较高的执行速度时,我们就得面对解决代码效率问题了。如何提高代码效率?现笔者以一个LED闪烁的程序为例与您探讨。
#i nclude<reg52.h>//包含头文件
sbit led=P2^0;//定义位变量led,使其关联单片机管脚P2.0
void Delayms(unsigned int t);//定义延时函数
int main(void)//主函数(C语言程序入口函数)
{
while(1)
{
led=0;//P2.0拉低,点亮LED
Delayms(500);//调用延时函数,延时500毫秒
led=1;//P2.0拉高,熄灭LED
Delayms(500);//调用延时函数,延时500毫秒
}
return 0;
}
void Delayms(unsigned int t)//延时函数
{
unsigned int i,j;
for(i=0;i<t;i++)
for(j=0;j<120;j++);//大约延时1毫秒
}
这是指示灯LED闪烁的C源码,这个源码在Keil uVision4 生成的程序代码是67个字节。下面我们就采用几个方法来提高这个程序的效率。
一.尽量定义局部变量
单片机程序的全局变量一般是放在通用数据存储器(RAM)中,而局部变量一般是放在特殊功能寄存器当中。处理寄存器数据的速度比处理RAM数据要快,如果在一个局部函数里调用一个全局变量将会多生成好几个代码出来。所以,少定义全局变量,多定义局部变量。如上例中,如果把延时函数里的i和j定义为全局变量,编译后程序代码会增加到79个字节,多了12个字节。
二.省略函数定义
在一个单片机程序里我们习惯在main函数的前面先定义被调用函数,然后在mian函数的下面再实现被调用函数。这样的写法固然是一个好习惯,但每定义一个函数会增加几个代码,而且函数形参数据类型越大、形参越多增加的代码就越多,显然这不是什么好事。如果不定义编译器又报错,怎么办?C编译器的编译顺序是从上往下编译,只要被调用的函数在主调函数调用之前实现就没有问题了。所以,笔者的习惯写法是不用定义函数,但要按先后顺序(被调用函数一定要在主调函数之前写好)来写函数实现,到最后再写main函数。这样做编译器不但不会报错,而且代码得到精简了。如上例中,把延时函数的定义删除了,然后把延时函数的实现搬到main函数的上面,编译后程序代码减少到63个字节,减少了4个字节。
三.省略函数形参
函数带形参,是为了在函数调用时传递实参,不但可以避免重复代码出现,还可以通过传递不同的实参值多次调用函数且实现不同的函数功能,总体代码也会得到精简。在实际编程的时候,我们只要注意,还可以进一步精简代码。对于不是多次调用或者多次调用但实参值不变的函数我们可以省略函数形参。如上例中的延时函数,我们把它改成不带形参的函数:
void Delayms()//延时函数
{
unsigned int i,j;
for(i=0;i<500;i++)
for(j=0;j<120;j++);//大约延时1毫秒
}
编译后,程序代码变成了56个字节,精简了11个字节。
四.改换运算符
也许您可能没有注意到C运算符的运用也会影响程序代码的数量。如上例中,把延时函数里的自加运算符改成自减运算符后,如:
void Delayms(unsigned int t)//延时函数
{
unsigned int i,j;
for(i=t;i>0;i--)
for(j=120;j>0;j--);//#p#分页标题#e#大约延时1毫秒
}
编译后,程序代码变成了65个字节,精简了2个字节。
通过改换运算符能达到精简代码的例子还有:
1.把求余运算表达式改为位与运算表达式。如:b=a%8 可以改为:b=a&7。
2.把乘法运算表达式改为左移运算表达式。如:b=a*8 可以改为:b=a<<3。
3.把除法运算表达式改为右移运算表达式。如:b=a/8 可以改为:b=a>>3。
五.选择合适的数据类型
C语言里选择变量的数据类型很讲究,变量的数据类型过小满足不了程序的要求,变量的数据类型过大会占用太多的RAM资源。您可能还没有注意到数据类型定义也影响程序代码的大小,而且这个影响还不小。如上例中,延时函数里的局部变量j定义的数据类型明显偏大,如果把它由unsigned int改成unsigned char 。编译后,程序代码变成了59个字节,精简了8个字节。
六.直接嵌入代码
在您的程序里如果某个函数只调用一次,而您又要求代码提高执行速度,建议您不要采用调用函数的形式,而应该将该函数里的代码直接嵌入主调函数里,代码执行效率会大大提高。
七.使用效率高的C语句
C语言里有一个三目运算符“?”,俗称“问号表达式”。很多程序员都很喜欢使用,因为它逻辑清晰表达简洁。
看这个问号表达式:c=(a>b) ? a+1 : b+1;实际上等效于以下的if…else结构:
if (a>b) c=a+1;
else c=b+1;
可以看到,使用问号表达式,语句相当简洁,但它的执行效率却很低,远没有if…else语句效率高。所以,当您的程序要求提高执行速度的话,建议您不要使用问号表达式了。
另外,do…while语句也比while语句的效率高。
更多的关于C语言代码的知识:代码的效率问题,不是我们编程中的主要问题,除了程序要求较高的执行速度或者单片机的ROM和RAM不够用的时候才会考虑。一般情况下,我们不用在乎。如果您一味追求高效率的代码,可能会影响代码的可读性和可维护性。
如何提高单片机C语言代码效率的更多相关文章
- 写出高效优美的单片机C语言代码
程序能跑起来并不见得你的代码就是很好的c代码了,衡量代码的好坏应该从以下几个方面来看 1,代码稳定,没有隐患. 2,执行效率高. 3,可读性高. 4,便于移植. 下面发一些我在网上看到的技巧和自己的一 ...
- Android 你可能忽略的提高敲代码效率的方式 (转)
每日推荐 Eyepetizer-in-Kotlin:一款简约的小视频app,带你走进kotlin 作为学习kotlin的一款app,在撸代码的过程中学习kotlin的语法及特性. Eyepetizer ...
- Android 你可能忽略的提高敲代码效率的方式
Android 你可能忽略的提高敲代码效率的方式
- 将python代码转化为c语言代码,提高运行效率
将python代码转化为c语言代码,提高运行效率 首先,需要安装cpython库: pip install cython 安装完成之后,写一段简单的代码,例如下面这个利用递归求斐波那契数列的函数,然后 ...
- 单片机C 语言与汇编语言混合编程
在单片机应用系统设计中,过去主要采用汇编语言开发程序. 汇编语言编写的程序对单片机硬件操作很方便,编写的程序代码短,效率高,但系统设计的周期长,可读性和可移植性都很差.C语言程序开发是近年来单片机系统 ...
- 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码
浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...
- 如何优化C语言代码(程序员必读)
1.选择合适的算法和数据结构 应该熟悉算法语言,知道各种算法的优缺点,具体资料请参见相应的参考资料,有很多计算机书籍上都有介绍.将比较慢的顺序查找法用较快的二分查找或乱序查找法代替,插入排序或冒泡排序 ...
- 【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则
作者:Williammao, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/290.h ...
- 【《Effective C#》提炼总结】提高Unity中C#代码质量的22条准则
引言 原则1尽可能地使用属性而不是可直接访问的数据成员 原则2偏向于使用运行时常量而不是编译时常量 原则3 推荐使用is 或as操作符而不是强制类型转换 原则4 推荐使用条件属性而不是if条件编译 原 ...
随机推荐
- S0.3 直方图
目录 直方图(一) 直方图概念 直方图分类 直方图优点 直方图应用 opencv3直方图产生函数cvCalcHist() 画图函数 完整示例 直方图(一) 直方图概念 直方图是图像中像素强度分布的图形 ...
- Linux epoll机制
epoll_create.epoll_ctl.epoll_wait.close 在linux的网络编程中,很长的时间都在使用select来做事件触发.在linux新的内核中,有了一种替换它的机制,就是 ...
- (70)Wangdao.com第十一天_JavaScript 日期对象 Date
日期对象 Date 表示一个时间 Date 对象是 JavaScript 原生的时间库 它以1970年1月1日00:00:00作为时间的零点,可以表示的时间范围是前后各1亿天(单位为毫秒) 时间零点( ...
- 关于finally代码块是否一定被执行的问题
一般来说,只要执行了try语句,finally就会执行 但是,有以下几种情况需要特殊考虑 具体例子看链接 点击这里 第一点 try代码块没有被执行,意思就是错误在try代码块之前就发生了. 第二点 ...
- 问题:CMD安装mysql-server遇到找不到MSVCR120.dll问题(已解决)
今天,我用CMD安装mysql服务器端遇到了找不到msvcr120.dll问题,所以我去网上下载这个dll,但是出现找不到入口,或者什么的. 我想了想,去下载运行时库(因为MSVCR是Microso ...
- linux安装zookeeper
安装环境:Linux:centos6.4Jdk:1.7以上版本 Zookeeper是java开发的可以运行在windows.linux环境.需要先安装jdk.安装步骤:第一步:安装jdk第二步:把zo ...
- ASP.NET Core 问题排查:Request.EnableRewind 后第一次读取不到 Request.Body
实际应用场景是将用户上传的文件依次保存到阿里云 OSS 与腾讯云 COS ,实现方式是在启用 Request.EnableRewind() 的情况下通过 Request.Body 读取流,并依次通过 ...
- Python 学习笔记6 变量-字典
字典是python中一个十分重要的变量,他是一个可变的容器对象.通过一组key(键)和value(值)对组成一个元素. 组成形式为{'key':'value', 'key':'value'}.整个字典 ...
- 关于parseInt()里的一些小坑
parseInt(string,radix)方法是将输入字符串转化为数值,两个输入参数中string为要转化的字符串,radix可省略,是浏览器以几进制来解读输入的string. 举几个例子就能够对该 ...
- maven插件--assembly
之前maven项目中使用assembly插件单独打包项目依赖包,项目只有一个模块也就一个pom,配置这个插件,一切很顺利.但是现在的项目复杂了,有parent有child,多模块.按照之前的做法怎么也 ...