6054|8

248

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

编写高效的C语言 [复制链接]

编写高效简洁的C语言代码,是许多软件工程师追求的目标。本文就是针对编程工作中的一些体会和经验做相关的阐述。

第一招:以空间换时间

计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题,我们就有了解决问题的第1招--以空间换时间。比如说字符串的赋值:

方法A:通常的办法


#define LEN 32
char string1 [LEN];
memset (string1,0,LEN);
strcpy (string1,"This is a example!!");




方法B:


const char string2[LEN] ="This is a example!";
char * cp;
cp = string2 ;


使用的时候可以直接用指针来操作。

从上面的例子可以看出,A和B的效率是不能比的。在同样的存储空间下,B直接使用指针就可以操作了,而A需要调用两个字符函数才能完成。B的缺点在于灵活性没有A好。在需要频繁更改一个字符串内容的时候,A具有更好的灵活性;如果采用方法B,则需要预存许多字符串,虽然占用了大量的内存,但是获得了程序执行的高效率。

如果系统的实时性要求很高,内存还有一些,那我推荐你使用该招数。该招数的变招--使用宏函数而不是函数。举例如下:

方法C:


#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
int BIT_MASK(int __bf)
{
 return ((1U << (bw ## __bf)) - 1)<< (bs ## __bf);
}
void SET_BITS(int __dst,
int __bf, int __val)
{
 __dst = ((__dst) & ~(BIT_MASK(__bf))) |
\
 (((__val) << (bs ## __bf))
& (BIT_MASK(__bf))))
}
SET_BITS(MCDR2, MCDR2_ADDRESS,ReGISterNumber);




方法D:


#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK(MCDR2_ADDRESS)
#define BIT_MASK(__bf)
(((1U << (bw ## __bf)) - 1)
<< (bs ## __bf))
#define SET_BITS(__dst, __bf, __val)
\
((__dst) = ((__dst) & ~(BIT_MASK(__bf)))
| \
(((__val) << (bs ## __bf))
& (BIT_MASK(__bf))))
SET_BITS(MCDR2, MCDR2_ADDRESS,
RegisterNumber);


函数和宏函数的区别就在于,宏函数占用了大量的空间,而函数占用了时间。大家要知道的是,函数调用是要使用系统的栈来保存数据的,如果编译器里有栈检查选项,一般在函数的头会嵌入一些汇编语句对当前栈进行检查;同时,CPU也要在函数调用时保存和恢复当前的现场,进行压栈和弹栈操作,所以,函数调用需要一些CPU时间。

而宏函数不存在这个问题。宏函数仅仅作为预先写好的代码嵌入到当前程序,不会产生函数调用,所以仅仅是占用了空间,在频繁调用同一个宏函数的时候,该现象尤其突出。

D方法是我看到的最好的置位操作函数,是ARM公司源码的一部分,在短短的三行内实现了很多功能,几乎涵盖了所有的位操作功能。C方法是其变体,其中滋味还需大家仔细体会。

第二招:数学方法解决问题

现在我们演绎高效C语言编写的第二招--采用数学方法来解决问题。数学是计算机之母,没有数学的依据和基础,就没有计算机的发展,所以在编写程序的时候,采用一些数学方法会对程序的执行效率有数量级的提高。举例如下,求 1~100的和。

方法E:


int I , j;
for (I = 1 ;I<=100; I ++)
{
 j += I;
}




方法F


int I;
I = (100 * (1+100)) / 2




这个例子是我印象最深的一个数学用例,是我的计算机启蒙老师考我的。当时我只有小学三年级,可惜我当时不知道用公式 N×(N+1)/ 2 来解决这个问题。方法E循环了100次才解决问题,也就是说最少用了100个赋值,100个判断,200个加法(I和j);而方法F仅仅用了1个加法,1次乘法,1次除法。效果自然不言而喻。所以,现在我在编程序的时候,更多的是动脑筋找规律,最大限度地发挥数学的威力来提高程序运行的效率。

第三招:使用位操作

实现高效的C语言编写的第三招——使用位操作。减少除法和取模的运算。在计算机程序中数据的位是可以操作的最小数据单位,理论上可以用"位运算"来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。举例如下:

方法G


int I,J;
I = 257 /8;
J = 456 % 32;




方法H


int I,J;
I = 257 >>3;
J = 456 - (456 >> 4 << 4);




在字面上好像H比G麻烦了好多,但是,仔细查看产生的汇编代码就会明白,方法G调用了基本的取模函数和除法函数,既有函数调用,还有很多汇编代码和寄存器参与运算;而方法H则仅仅是几句相关的汇编,代码更简洁,效率更高。当然,由于编译器的不同,可能效率的差距不大,但是,以我目前遇到的MS C ,ARM C 来看,效率的差距还是不小。相关汇编代码就不在这里列举了。

运用这招需要注意的是,因为CPU的不同而产生的问题。比如说,在PC上用这招编写的程序,并在PC上调试通过,在移植到一个16位机平台上的时候,可能会产生代码隐患。所以只有在一定技术进阶的基础下才可以使用这招。

第四招:汇编嵌入

高效C语言编程的必杀技,第四招——嵌入汇编。"在熟悉汇编语言的人眼里,C语言编写的程序都是垃圾"。这种说法虽然偏激了一些,但是却有它的道理。汇编语言是效率最高的计算机语言,但是,不可能靠着它来写一个操作系统吧?所以,为了获得程序的高效率,我们只好采用变通的方法--嵌入汇编,混合编程。举例如下,将数组一赋值给数组二,要求每一字节都相符。

char string1[1024],string2[1024];

方法I


int I;
for (I =0 ;I<1024;I++)
 *(string2 + I) = *(string1 + I)




方法J


#ifdef _PC_
int I;
for (I =0 ;I<1024;I++)
*(string2 + I) = *(string1 + I);
#else
#ifdef _ARM_
__asm
{
 MOV R0,string1
 MOV R1,string2
 MOV R2,#0
loop:
 LDMIA R0!, [R3-R11]
 STMIA R1!, [R3-R11]
 ADD R2,R2,#8
 CMP R2, #400
 BNE loop
}
#endif




方法I是最常见的方法,使用了1024次循环;方法J则根据平台不同做了区分,在ARM平台下,用嵌入汇编仅用128次循环就完成了同样的操作。这里有朋友会说,为什么不用标准的内存拷贝函数呢?这是因为在源数据里可能含有数据为0的字节,这样的话,标准库函数会提前结束而不会完成我们要求的操作。这个例程典型应用于LCD数据的拷贝过程。根据不同的CPU,熟练使用相应的嵌入汇编,可以大大提高程序执行的效率。

虽然是必杀技,但是如果轻易使用会付出惨重的代价。这是因为,使用了嵌入汇编,便限制了程序的可移植性,使程序在不同平台移植的过程中,卧虎藏龙,险象环生!同时该招数也与现代软件工程的思想相违背,只有在迫不得已的情况下才可以采用
此帖出自编程基础论坛

最新回复

即使是转发,能在这里看到它,也增长了不少的见识。  详情 回复 发表于 2012-5-23 14:09
点赞 关注
 

回复
举报

4

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
楼主真是牛人啊!拜读了
此帖出自编程基础论坛
 
 
 

回复

5

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
[原创] ▓ARM 2440-stm32视频-dsp-CPLD-FPGA-PADS开发视频-嵌入式系统开发-单片机开发视频

▓ARM 2440-stm32视频-dsp-CPLD-FPGA-PADS开发视频-嵌入式系统开发-单片机开发视频
=======(基于2440的视频教程)嵌入式Linux视频培训视频教程=======
视频文件列表:
第一部分:(Linux系统管理)
(嵌入式系统概述)
Linux介绍)
(Linux定制安装)
Linux命令1
Linux命令2
VI使用
系统管理)
Shell编程)
GCC程序编译)
GDB程序调试)
Makefile工程管理)
第二部分:
库函数方式访问文件)
系统调用方式访问文件)
时间编程)
进程控制理论)
进程创建
进程等待
进程通讯概述
管道通讯)
信号通讯)2-3-3
共享内存通讯)
(消息队列)2-4-1
(线程创建)2-5-1
第2阶段\第五天(多线程)\2-5-2(线程等待与清除)
(ARM程序设计)(ARM概述)
(ARM程序设计)(mini2440)
(ARM程序设计)(ARM寄存器)
(ARM程序设计)(ARM寻址方式)
(ARM程序设计)(ARM指令1)
(ARM程序设计)\第一部分(体系结构指令)\3-1-6(ARM指令2)
第三部分:(内核开发)
内核简介
Linux内核源代码)4-1-2
Linux内核配置与编译)
Linux内存管理)4-2-1
(Linux进程与内核地址空间)
Linux内核链表)
内核定时器)
内核进程)
进程调度)
系统调用)
Proc文件系统)
异常分析)
交叉工具链)
嵌入式系统构建)
bootloader介绍)
Uboot简介)
UBoot命令)
Uboot移植)
第四张部分:(驱动程序设计)
Linux驱动程序介绍)
字符设备驱动)
简单字符设备驱动实例分析)
并发控制)5-1-4(并发控制)
Ioctl设备控制)
内核等待队列)
阻塞型字符设备驱动)
poll设备方法)
自动创建设备文件)
mmap设备方法)
硬件访问)
LED驱动程序)
总线)
设备)
驱动)
platform驱动)
中断处理程序)
按键驱动)
网卡驱动程序设计)
CS8900A网卡驱动程序分析)
输入子系统)
触摸屏驱动程序)
PCI总线)
PCI驱动程序设计)
串口驱动程序)
===============================================
=======ARM STM32视频教程 +配套工程源代码=========
第一讲 ARM处理器和STM32微控制器(37分钟)
ARM处理器家族
    -ARM7系列介绍
    -ARM9系列介绍
    -ARM10和ARM11系列介绍
    -ARM Cortex系列介绍
ARM Cortex-M3的应用介绍
STM32微控制器
    -特征和资源讲解
    -管脚的配置灵活性讲解(即管脚的重映射功能)
    -微控制器功能框图讲解
开发工具IAR EWARM介绍
STM32微控制器最小系统
    -电源电路讲解(芯片电源功能块及开发板电源电路设计讲解)
    -时钟电路讲解(芯片时钟树及开发板时钟电路设计讲解)
    -复位电路讲解(芯片复位功能块及开发板手动和上电复位电路设计讲解)
    -启动配置电路讲解(芯片启动模式的讲解)
    -调试电路讲解(调试电路接口设计和所需仿真器讲解)
STM32微控制器的应用领域介绍
第二讲  STM32固件库说明及移植到IAR EWARM中的详细过程(33分钟)
IAR EWARM破解版的详细安装方法讲解(包括ST公司提供的更新文件的安装)
STM32固件库介绍
    -固件库的功能介绍
    -固件库的特点及有点介绍
    -固件库内部各源文件详细介绍
移植STM32固件库到IAR EWARM及IDE的操作方法
    -良好的工程创建的习惯(以GPIO的操作为例)
    -编译设置中的各选项详细讲解
    -编译成功的输出文件说明

第三讲  触摸屏的使用(14分钟)
    -电阻触摸屏的结构介绍
   -使用ADC来获取X,Y轴的坐标原理
   -程序详解
第四讲  存储器和总线结构(19分钟)
  -总线结构讲解
   -理解内部存储器的分配
   -lnkarm_flash.xcl和lnkarm_ram.xcl文件的理解
第五讲  RCC的配置和使用(55分钟)
     -理解各种复位
   -时钟树分析
   -Systick 系统嘀嗒定时器的讲解
   -相关寄存器理解
   -相关库函数的理解
   -程序讲解
第六讲 EXTI和NVIC的配置和使用(34分钟)
-STM32中的NVIC的理解
   -NVIC的寄存器和库函数的理解
   -STM32中的EXTI的理解
   -EXTI的寄存器和库函数的理解
   -程序讲解
      -外部模拟中断输入测试实验
第七讲 STM32的GPIO和AFIO的配置和应用(54分钟)

STM32的GPIO
    -GPIO资源介绍
    -GPIO工作模式讲解
    -GPIO的特点讲解
STM32的AFIO
    -芯片中的AFIO资源讲解
    -使用AFIO的方法和操作要领讲解
GPIO的初始化要素
    -选取工作管脚的参数配置讲解
    -选取管脚工作模式参数配置讲解
    -选取管脚速率参数配置讲解
AFIO的使用
    -如何映射功能块到相应管脚的方法讲解
GPIO和AFIO的寄存器讲解
GPIO的库函数讲解
工程源程序讲解
    -跑马灯实验详解(GPIO的输出操作)
    -按键识别和LED指示实验详解(GPIO的输入和输出操作)

第八讲    I2C总线(96分钟)

I2C总线中的概念讲解
I2C总线应用实例
    -以无绳电话基站为例来总结I2C接口通信的特点和注意事项的讲解
I2C总线的操作要素
    -工作模式讲解
    -数据的有效性讲解
    -传输开始和停止条件讲解
    -数据传输格式讲解
    -寻址方式讲解
    -仲裁和时钟同步讲解
基于I2C总线的读写工作过程
    -写数据通讯过程讲解
    -读数据通讯过程讲解
EEPROM AT24C02 的操作
    -特点讲解
    -各种写操作讲解
    -各种读操作讲解
软件模拟I2C时序
    -I/O模拟开始信号、停止信号、提供时钟信号、发送ACK、发送一个字节数据和接收一个字节数据的时序模拟讲解
    -连续多字节写函数伪代码实现讲解
    -连续多字节读函数伪代码实现讲解
STM32中的I2C控制器
    -特点讲解
    -I2C总线中出现的错误讲解
    -I2C中DMA的特性讲解
    -I2C主发送器工作流程讲解
    -I2C主接收工作流程讲解
STM32中的I2C控制器的寄存器详解
I2C库函数详解

工程源程序讲解
    -STM32的I2C控制器对AT24C02的各种操作功能函数的详解

第九讲 TFT模块的字符、中文和图片显示(26分钟)
TFT模块
    -特点介绍
    -坐标系和引脚讲解
TFT模块的配置和取模软件的取模原理
    -TFT模块的常用配置讲解(包括数据格式和扫描模式等)
    -取模软件为中文和图片取模的原理讲解
工程源程序讲解
    -字符显示功能函数讲解(含ASCII码表分析)
    -图片显示功能函数讲解
    -16*16中文显示功能函数讲解
    -48*48中文显示功能函数讲解
第十讲  单总线(33分钟)
DS18B20讲解
    -特点讲解
    -功能框图详解
    -各种寄存器及温度输出数据格式讲解
    -电源供电方法介绍
单总线讲解
    -特点讲解
    -硬件设计讲解
    -命令序列讲解
        -初始化
        -ROM命令
        -功能命令
    -信号时序讲解(即软件模拟)
        -复位脉冲和应答脉冲
        -写时隙
        -读时隙
工程源程序讲解
    -使用GPIO来操作DS18B20的各种功能你函数详解
第十一讲   SPI总线(85分钟)
SPI总线介绍
SPI总线的通讯时序(即软件模拟SPI通讯时序)
    -通讯框图讲解
    -四种SPI通讯时序讲解
    -GPIO模拟发送一位数据时序讲解
    -GPIO模拟接收一位数据时序讲解
    -GPIO模拟写一个字节数据的伪代码实现讲解
    -GPIO模拟读一个字节数据的伪代码实现讲解
STM32中的SPI控制器
    -特点介绍
    -NSS引脚的软硬件管理详解
    -SPI接口硬件设计讲解(全双工和单工通讯等)
    -使用硬件SPI容易出错的地方和操作要领讲解
FLASH AT45DB161D的操作
    -特点介绍
    -内部存储组织讲解
    -各种读写时序讲解
    -各种读写指令讲解
    -擦除指令讲解

STM32中的SPI控制器的寄存器详解
SPI的库函数详解

工程源程序讲解
    -STM32的SPI控制器对AT45DB161D的各种操作功能函数详解

第十二讲  SMT32中的ADC操作(88分钟)
ADC的特点讲解
ADC的功能框图讲解
ADC的各种转换模式讲解(包含规则组和注入组的操作原理和注意事项)
ADC的采样时间设置讲解
ADC的数据对齐讲解
ADC的模拟看门狗作用和使用讲解
ADC中的DMA特性和配置讲解
双ADC工作模式详解
ADC的寄存器讲解
ADC的库函数讲解

工程源程序讲解
    -单通道连续转换且使用DMA传输的功能程序详解
    -单通道连续转换且使用DMA传输和模拟看门狗,并实时更新报警标志的功能程序讲解
第十三讲  CAN总线(124分钟)

典型CAN总线网络系统结构详解(包括各组成部分的功能讲解)
CAN总线中的基本概念分析讲解
CAN总线的报文传输和结构讲解
    -各报文类型
    -各报文帧格式
    -位定时
    -帧间间隙
    -位填充
CAN总线特点讲解
STM32中的CAN控制器
    -特点讲解
    -功能框图讲解
    -工作模式讲解
    -初始化配置和参数设置讲解
    -发送数据操作讲解
    -接收数据操作讲解
    -过滤器工作原理讲解
    -接收FIFO工作过程讲解
    -总线出错管理讲解
    -位时序讲解

CAN控制器的寄存器详解
CAN控制器的库函数详解

工程源程序讲解
    -单块板的自测试详解(包括查询和中断方式,也含标准帧和扩展帧传输)
    -2块板的通信测试-查询方式详解
    -2块板的通信测试-中断方式详解
第十四讲 RTC和BKP(72分钟)
      -RTC模块要点讲解
    -RTC寄存器讲解
   -BKP特点
   -BKP寄存器讲解
   -RTC和BKP库函数讲解
   -例程详解
---------另有------------------
=======第一部分单片机相关======
1【单片机多媒体视频教程】(汇编)非常经典
2【单片机入门与提高精品视频教程】(汇编),非常适合初学者.
3【手把手教你学单片机 51单片机 C语言 视频教程 从入门到精通 视频】
4【数电/模电精品视频教程】,非常适合初学者.
5【汇编语言精品视频教程】,非常适合初学者.
6【单片机的C语言编程及电路设计培训视频教程】
7【标准C语言入门与提高视频教程】非常经典
8【AVR单片机入门与提高视频】
9【MSP430单片机经典视频】
10【PIC单片机经典视频】
11【电路分析应用技术视频】
======第二部分电路设计相关=========
【protel99se+DXP/2004 视频教程+实例】
【Protel(Altium Desinger)】电路设计视频教程
【Cadence经典视频教程】
【Orcad经典视频教程】
【PowerPCB入门视频教程】
=====第三部分嵌入式硬件部分========
1【ARM linux培训视频】
2【手把手教你学ARM之LPC2103入门篇 视频教程】
3【ARM STM32视频教程 +配套工程源代码】
4【(基于2440开发板的视频教程)嵌入式Linux视频培训视频】
5《学ARM和学单片机一样简单》视频】
6【ARM嵌入式LPC2200视频教学视频教程《嵌入式系统与结构》 】
7【ARM7嵌入式S3C44B0视频教学《嵌入式微处理器原理及应用》】
8【ARM嵌入式视频《嵌入式原理与应用》】
9【 台湾嵌入式培训】
10【嵌入式系统开发技术视频】
11【Altera FPGA 视频教程】
12【深入浅出玩转FPGA视频】
13【EDA(CPLD FPGA)入门与提高视频教程】
14【dsp入门与提高视频教程】   
15【DSP多媒体教程】
16【vhdl应用技术视频】
17【PLC精品视频】                  
18【数控应用经典技术视频】

=====第四部分嵌入式软件部分====
1,【Windows CE入门与提高视频教程】       2,【Vxworks应用技术】
3,【linux编程入门与提高视频教程】  4 【linux工程师软件开发视频】
5,【eCos、uC/OS-II开发技术】             6,【C++编程入门与提高视频教程】
7,【嵌入式仿真开发】
8,【JAVA开发视频】                       9,【.net开发视频】
→篇幅有限,更多内容请联系
Q_Q:7-5-9-7-3-7-8-3-3

MSN:jxb200200@hotmail.com
更多内容请登陆知心365学习中心-网站 www.zhixin365.net
此帖出自编程基础论坛
 
 
 

回复

220

帖子

0

TA的资源

一粒金砂(中级)

4
 
看来我能力见长,竟然从中看出来了点什么:Q
此帖出自编程基础论坛
 
 
 

回复

77

帖子

0

TA的资源

纯净的硅(初级)

5
 
      哥们太犀利了!看来我接触的C太简单了!高手真是层出不穷!在下有理了!
此帖出自编程基础论坛
 
 
 

回复

547

帖子

0

TA的资源

纯净的硅(初级)

6
 
好厉害!!!!
此帖出自编程基础论坛
 
个人签名嵌入式培训www.51great.org
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

7
 
没营养的转发帖!
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

196

帖子

0

TA的资源

一粒金砂(中级)

8
 
很强悍!!!
此帖出自编程基础论坛
 
 
 

回复

304

帖子

0

TA的资源

一粒金砂(高级)

9
 
即使是转发,能在这里看到它,也增长了不少的见识。
此帖出自编程基础论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表