C语言程序优化原则举例_为什么要用汇编优化c,怎样的优化是有效的,怎么个优化原则-程序员宅基地

技术标签: 语言  c  编译器  delay  优化  Programming C  数据结构  

 

1、选择合适的算法和数据结构 
应该熟悉算法语言,知道各种算法的优缺点,具体资料请参见相应的参考资料,有
很多计算机书籍上都有介绍。将比较慢的顺序查找法用较快的二分查找或乱序查找
法代替,插入排序或冒泡排序法用快速排序、合并排序或根排序代替,都可以大大
提高程序执行的效率。.选择一种合适的数据结构也很重要,比如你在一堆随机存
放的数中使用了大量的插入和删除指令,那使用链表要快得多。
数组与指针语句具有十分密码的关系,一般来说,指针比较灵活简洁,而数组则比
较直观,容易理解。对于大部分的编译器,使用指针比使用数组生成的代码更短,
执行效率更高。但是在Keil中则相反,使用数组比使用的指针生成的代码更短。。


2、使用尽量小的数据类型
能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用
整型变量定义的变量就不要用长整型(long int),能不使用浮点型(float)变量就
不要使用浮点型变量。当然,在定义变量后不要超过变量的作用范围,如果超过变
量的范围赋值,C编译器并不报错,但程序运行结果却错了,而且这样的错误很难
发现。在ICCAVR中,可以在Options中设定使用printf参数,尽量使用基本型参数

(%c、%d、%x、%X、%u和%s格式说明符),少用长整型参数(%ld、%lu、%lx和%lX格式说明符),

至于浮点型的参数(%f)则尽量不要使用,其它C编译器也一样。在其它条件不变的情况下,

使用%f参数,会使生成的代码的数量增加很多,执行速度降低。

3、使用自加、自减指令
通常使用自加、自减指令和复合赋值表达式(如a-=1及a+=1等)都能够生成高质量的
程序代码,编译器通常都能够生成inc和dec之类的指令,而使用a=a+1或a=a-1之类
的指令,有很多C编译器都会生成二到三个字节的指令。在AVR单片适用的

ICCAVR、GCCAVR、IAR等C编译器以上几种书写方式生成的代码是一样的,

也能够生成高质量的inc和dec之类的的代码。

4、减少运算的强度
可以使用运算量小但功能相同的表达式替换原来复杂的的表达式。如下:
(1)、求余运算。
    a=a%8;
可以改为:
    a=a&7;
说明:位操作只需一个指令周期即可完成,而大部分的C编译器的“%”运算均是调
用子程序来完成,代码长、执行速度慢。通常,只要求是求2n方的余数,均可使用
位操作的方法来代替。

(2)、平方运算
    a=pow(a,2.0);
可以改为:
    a=a*a;
说明:在有内置硬件乘法器的单片机中(如51系列),乘法运算比求平方运算快得多
,因为浮点数的求平方是通过调用子程序来实现的,在自带硬件乘法器的AVR单片
机中,如ATMega163中,乘法运算只需2个时钟周期就可以完成。既使是在没有内置
硬件乘法器的AVR单片机中,乘法运算的子程序比平方运算的子程序代码短,执行
速度快。
如果是求3次方,如:
    a=pow(a,3.0);
更改为:
    a=a*a*a;
则效率的改善更明显。

(3)、用移位实现乘除法运算
    a=a*4;
    b=b/4;
可以改为:
    a=a<<2;
    b=b>>2;
说明:通常如果需要乘以或除以2n,都可以用移位的方法代替。在ICCAVR中,如果
乘以2n,都可以生成左移的代码,而乘以其它的整数或除以任何数,均调用乘除法
子程序。用移位的方法得到代码比调用乘除法子程序生成的代码效率高。实际上,
只要是乘以或除以一个整数,均可以用移位的方法得到结果,如:
    a=a*9
可以改为:
    a=(a<<3)+a

5、循环
(1)、循环语
对于一些不需要循环变量参加运算的任务可以把它们放到循环外面,这里的任务包
括表达式、函数的调用、指针运算、数组访问等,应该将没有必要执行多次的操作
全部集合在一起,放到一个init的初始化程序中进行。

(2)、延时函数:
通常使用的延时函数均采用自加的形式:
    void delay (void)
    {
unsigned int i;
    for (i=0;i<1000;i++)
    ;
    }
将其改为自减延时函数:
    void delay (void)
    {
unsigned int i;
        for (i=1000;i>0;i--)
    ;
    }
两个函数的延时效果相似,但几乎所有的C编译对后一种函数生成的代码均比前一
种代码少1~3个字节,因为几乎所有的MCU均有为0转移的指令,采用后一种方式能
够生成这类指令。
在使用while循环时也一样,使用自减指令控制循环会比使用自加指令控制循环生
成的代码更少1~3个字母。
但是在循环中有通过循环变量“i”读写数组的指令时,使用预减循环时有可能使
数组超界,要引起注意。

(3)while循环和do…while循环
用while循环时有以下两种循环形式:
unsigned int i;
    i=0;
    while (i<1000)
    {
        i++;
   //用户程序
    }
或:
unsigned int i;
    i=1000;
    do
    i--;
    //用户程序
    while (i>0);
在这两种循环中,使用do…while循环编译后生成的代码的长度短于while循环。

6、查表
在程序中一般不进行非常复杂的运算,如浮点数的乘除及开方等,以及一些复杂的
数学模型的插补运算,对这些即消耗时间又消费资源的运算,应尽量使用查表的方
式,并且将数据表置于程序存储区。如果直接生成所需的表比较困难,也尽量在启
了,减少了程序执行过程中重复计算的工作量。

 

7、其它
比如使用在线汇编及将字符串和一些常量保存在程序存储器中,均有利于优化

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ezrasa/article/details/5468606

智能推荐

前端事件系统(二)_整个系统怎么监听事件 前端-程序员宅基地

文章浏览阅读108次。本章将把重点放在于对于事件的委托机制,以及jquery的事件绑定方法做一些解析。本章并没有什么比较难懂的地方,也还没有深入到jQuery的事件系统内部。事件委托上一章讲了前端事件系统以及简单地对各个浏览器进行兼容的方法。对于要求不高的页面来说,之前的简单事件注册,就可以很好的胜任各种各样的工作了。但是,试想一种情况。倘若一个页面有着极大量的事件绑定的需求,那么我们之前的事件系统,就不得不一..._整个系统怎么监听事件 前端

linux 系统调用hook_linux hook-程序员宅基地

文章浏览阅读265次。都引流到某乎上了,不准备在这继续发展了。_linux hook

gitlab ci 流水线上传 Job Artifacts 报 413 Request Entity Too Large 错误_git request entity too large-程序员宅基地

文章浏览阅读238次,点赞5次,收藏9次。极狐GitLab CI 问题解决。_git request entity too large

机器学习实战案例:使用线性回归构建房价预测模型_1. 构建一个简单的线性回归,使用 rm(房间数量)作为预测变量来预测 medv(房价)。一-程序员宅基地

文章浏览阅读1.7k次。Boston房价预测是机器学习过程中一个关于线性回归的问题,属于监督学习。本文通过对Boston房价进行分析,进行机器学习模型训练。本文所使用的的数据集下载:Boston_housing_predict。下面给出数据集中各列名称的定义:CRIM: 城镇人均犯罪率ZN: 住宅用地所占比例INDUS: 城镇中非住宅用地所占比例CHAS: 虚拟变量,用于回归分析NOX: 环保指数RM: 每栋住宅的房间数AGE: 1940 年以前建成的自住单位的比例DIS: 距离 5 个波士顿的就业中心的加权距离_1. 构建一个简单的线性回归,使用 rm(房间数量)作为预测变量来预测 medv(房价)。一

100个常用Arduino传感器库_arduino传感器驱动库-程序员宅基地

文章浏览阅读366次。原文地址。_arduino传感器驱动库

使用bfg快速清理git历史大文件_bfg git-程序员宅基地

文章浏览阅读2.3k次。文章目录git清理历史大文件步骤脚本清理服务器git清理历史大文件之前写过一篇的,使用的git命令清理的大文件,但是我3G多的git,.git文件夹里面的pack就3G多,而且是个好几年并且在持续开发的项目,里面的提交成千上万了,每次使用git filter-branch,都要好几个小时,我研究了一下,要彻底清理项目中的那一堆大文件,只要要用脚本连续跑两天。。。最近发现了一个方案,使用bfg,我仅仅十几分钟就处理完了原先的方案:https://blog.csdn.net/qq_36254947/a_bfg git

随便推点

python中的write字体大小_Python os.write() 方法-程序员宅基地

文章浏览阅读1.6k次。Python os.write() 方法概述os.write() 方法用于写入字符串到文件描述符 fd 中. 返回实际写入的字符串长度。在Unix中有效。语法write()方法语法格式如下:os.write(fd, str)参数fd -- 文件描述符。str -- 写入的字符串。返回值该方法返回写入的实际位数。实例以下实例演示了 write() 方法的使用:#!/usr/bin/python# -..._python编程write函数大小

DTO--数据传输对象_dto文件-程序员宅基地

文章浏览阅读556次。101 什么是DTO102 域DTO103 定制DTO104 数据传送哈希表105 数据传送行集106 案例系统的层间数据传输107 DTO生成器层间数据传输的过程就是服务的执行者将数据返回给服务的调用者的过程。在非分布式系统中由于有类似Open session in view这样的“怪胎解决方案”的存在,所以层间数据传输的问题并没有充分暴露出来,但是在分布式_dto文件

rails ajax,Rails Ajax 成功使用xmlHttpRequest-程序员宅基地

文章浏览阅读172次。用了rails后,好久没有用xmlHttpRequest对象了,因为rails把xmlHttpRequest给封装了,rails自带了很多ajax方法,今天用了下xmlhttprequest,还真遇到不少麻烦测试通过:opera 9.6 + IE 6.0 + FF 3 + chrome 2html:javascript:function createXmlHttpRequest(){//创建对象t..._s = xmlhttp.responsetext.tostring();

yolov8学习以及地下城数据标注训练_dnf yolo-程序员宅基地

文章浏览阅读2.6k次,点赞5次,收藏36次。该流程为加载模型配置 yolov8n.yaml, 加载权重yolov8n.pt,训练数据,验证数据,推理,导出onnx (导出一般用不到)4.将上面代码保存运行python main.py, 结果打印得到保存的目录,目录下有best.pt则是基于yolov8n.pt训练的。设置自动保存,修改标注的xml的保存目录,完成后开始画框标注,这里应该会出现predefined_classes.txt内的提示标签。上面为官网的代码配置文件在目录中有说明。2.解压进入根目录新建main.py。1.首先就是下载源码。_dnf yolo

编写自用油猴脚本踩坑记录-程序员宅基地

文章浏览阅读811次,点赞11次,收藏16次。也算是实现了这个小小的需求吧,不只是闷头干代码,还需要了解的是,油猴的沙盒机制,不然没有办法自动化执行。[油猴脚本开发指南]沙盒机制的前世今生-油猴中文网。

【阶段1】【动态规划】【对顶堆】_给定一个整数数组 a(其长度为 n),以及一个查询列 表,每一个查询列表区间由两个整-程序员宅基地

文章浏览阅读233次。【题意】给定一个长度为N的整数数组A,你需要创建另一个长度为N的整数数组B,数组B被分为K个连续的部分,并且如果i和j在同一个部分,则B[i]=B[j]。如果要求数组B能够满足Σ|A[i]-B[i]|最小,那么最小值是多少,请你输出这个最小值。【输入格式】输入包含多组测试数据。对于每组测试数据,第一行包含两个整数N和K。接下来N行每行包含一个整数,表示完整的数组A。当输入为一行0 0时,表示输入终止。【输出格式】对于每组数据,输出一个最小值。每个结果占一行。【数据范围】1≤N≤20._给定一个整数数组 a(其长度为 n),以及一个查询列 表,每一个查询列表区间由两个整

推荐文章

热门文章

相关标签