下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、嵌入式系统C语言编程基础,杨高波,SNBC,Page 2,目录,关于本课程 C语言复习 编程规范 开发高效程序的技巧,Page 3,为什么学习本课程,会C语法与会用C语言写程序是两个概念 C的灵活性以及由此而产生的陷阱非常多 The Most Beautiful Language and Most Dangerous Language in the Programming World! 本课程将嵌入式系统中最基本的(最经常用到的)概念与技巧介绍给大家,Page 4,小测验?,Page 5,Quiz 1,所有嵌入式系统的主流程最后都进入一个死循环,怎样用C语言实现一个死循环?,Page 6,Qu
2、iz 2,while().和do.while()有什么区别?,Page 7,Quiz 3,用变量a给出下列定义: 一个整型数 一个指向整型数的指针 一个有10个整型数的的数组 一个有10个指针的数组,该指针是指向一个整型数的,Page 8,Quiz 4,关键字static的作用是什么?,Page 9,Quiz 5,关键字const的作用是什么?,Page 10,Quiz 6,定义一个标准宏MIN ,这个宏输入两个参数并返回较小的一个。,Page 11,Quiz 7,嵌入式系统中经常要对变量或寄存器进行位操作。给定一个int型变量a,写两段代码,第一个将a的bit 3置为1,第二个将a的bit
3、3置为0。以上两个操作中,要保持其它位不变。,Page 12,Quiz 8,嵌入式系统具有经常去直接访问物理地址的特点。在某工程中,要求设置一绝对地址为0 x5a00 的整型变量的值为0 xaa55。写代码去完成这一任务。,Page 13,Quiz 9,下面这段代码的输出是什么?void foo(void)unsigned int a = 6;int b = -20;(a+b 6) ? puts(6) : puts(6);,Page 14,Quiz 10,请评论下面一段程序代码:void test()char string10;char *str = “0123456789”;strcpy(s
4、tring,str);,Page 15,Quiz 11,请评论下面一段程序代码:void GetMemory(char *p)p = (char *)malloc(0 x20);void Test(void)char *str = NULL;GetMemory(str);strcpy(str,”Hello World!”);printf(str);,Page 16,Quiz 12,中断是嵌入式系统的重要组成部分。请评论下面一段中断服务子程序代码:_interrupt double compute_area (double radius)double area = PI * radius * r
5、adius;printf(nArea = %f, area);return area;,Page 17,Answer!,Page 18,Quiz 1 Answer,while(1).,Page 19,Quiz 2 Answer,while().为入口条件循环,即在每次执行循环之前先检查判断条件;do.while()为退出条件循环,即在执行循环之后再检查判断条件。,Page 20,Quiz 3 Answer,a) int a;b) int *a;c) int a10;d) int *a10;,Page 21,Quiz 4 Answer,在C 语言中,关键字static 有三个明显的作用:1) 在
6、函数体内,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。,Page 22,Quiz 5 Answer,const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 const常量与#define常量:前者有数据类型,后者只是字符替换(而且可能产生意料不到的错
7、误),所以编译器可以对前者进行安全性检查。,Page 23,Quiz 6 Answer,#define MIN(A,B) (A) = (B) ? (A) : (B) #define宏的副作用,下面的代码执行后会发生什么事:least = MIN(*p+, b);,Page 24,Quiz 7 Answer,const int BIT3 = 0 x013;static int a;void SetBit3(void)a |= BIT3;void ClearBit3(void)a ,Page 25,Quiz 8 Answer,int *ptTemp = (int *)0 x5a00;*ptTemp
8、 = 0 xaa55;,Page 26,Quiz 9 Answer,输出为“6”,原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。 因此-20 变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。,Page 27,Quiz 10 Answer,字符串str需要11个字节才能存放下(包括末尾的0),而string只有10个字节的空间,所以strcpy会导致数组越界。,Page 28,Quiz 11 Answer,编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是_p,编译器使 _p =
9、p。本例中,_p申请了新的内存,但只是_p的值改变了,p的值却丝毫未变,仍然为NULL。事实上,每执行一次GetMemory就会泄漏一块内存。,Page 29,Quiz 12 Answer,1)ISR不能返回值;2)不能向ISR传递参数;3)ISR应该是短而有效率的,因而在ISR中做浮点运算、使用printf等是不明智的,会经常有重入和性能上的问题。,Page 30,还是先复习一下C吧!,Page 31,C语言复习,1)循环与分支2)作用域与存储类3)内存与指针4)位操作5)预编译处理,Page 32,循环与分支,1)几种循环语句:for(initialize;test;update)body
10、;while(test)body;dobody;while(test); 2)循环辅助手段:break语句用于跳出循环,continue语句用于结束本次循环。,Page 33,循环与分支,3)三种形式的if语句:if(expression).if(expression).else.if(expression1).else if(expression).else.,Page 34,循环与分支,4)条件运算符?: expression1 ? expression2 : expression3 如果expression1为真,整个表达式的值为expression2的值,否则为expression3的
11、值; 是if.else.的简写形式,但是编译器可以产生比if.else.更优化的代码。,Page 35,循环与分支,5)多重选择:switchswitch(expression)case constant1: statements; break;case constant2: statements; break;.default: statements; break;switch判断表达式必须具有整数值,case标签必须是整数常量或整数常量表达式。,Page 36,C语言复习,1)循环与分支2)作用域与存储类3)内存与指针4)位操作5)预编译处理,Page 37,作用域与存储类,1)作用域 代
12、码块作用域(局部变量)代码块:包含在开始花括号和对应结束花括号之内的一段代码。作用域:从定义变量位置到该代码块的末尾。 文件作用域(全局变量)在所有函数之外定义的变量具有文件作用域。作用域:从定义变量位置到包含该定义的文件的结尾处。在其它位置使用该变量应用extern来声明该变量。,Page 38,作用域与存储类,2)存储时期 静态存储时期:程序运行期间一直存在,给变量分配固定的存储空间;所有全局变量具有静态存储时期(具有静态存储时期的并不都是全局变量),但是修饰全局变量的关键词static表明的是链接类型,并非存储时期。 动态(自动)存储时期:运行期间根据需要动态的给变量分配存储空间。,Pa
13、ge 39,作用域与存储类,3)5种存储类,Page 40,C语言复习,1)循环与分支2)作用域与存储类3)内存与指针4)位操作5)预编译处理,Page 41,内存与指针,1)内存分配方式 从静态存储区分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量; 从栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限; 动态内存分配。程序在运行的时候由程序员自己负责申请和释放内存。,Page 42,内存与指针,2)内存陷阱 C
14、语言的灵活性,指针的应用,以及C语法的宽容性很容易造成代码的错误,这其中最主要的就是内存单元的溢出。a) 堆栈溢出b) 数组越界. 将错误锁定在一个函数中以后,首先应该关注内存的问题。,Page 43,内存与指针,举例,看看下面这段代码有什么问题char *DoSomething()char i32*1024;.return i;,两个重大问题:1、临时变量在堆栈上创建,太大的临时变量数组会冲掉堆栈;2、返回堆栈中的地址是没有意义的,因为堆栈中的内容永远是不确定的。,Page 44,内存与指针,数组越界的危险 临时数组:在栈上创建,因此临时数组越界有可能导致某些局部变量莫明其妙被改,函数返回时
15、崩溃等等; 全局数组:在静态存储区创建,因此全局数据越界有可能导致某些全局变量莫明其妙被改,被冲的动态内存无法释放等等。,Page 45,内存与指针,3)指针 指针是什么?指针是一个变量,它的值是另外一个变量的地址。 指针的类型指针所指向的变量的类型,就是指针的类型。举例,右边的运算有何不同:int X2, *pX=,Page 46,内存与指针,指针的三要素 1、指针指向的地址;2、指针指向地址上的内容;3、指针本身的地址; 举例:int A, *pA, *ppA;pA = ,Page 47,内存与指针,指针的大小(指针变量占用的内存空间) 举例,以下为ARM平台下的一段32位C程序,请计算s
16、izeof的值。char str = “Hello”;char *p = str;int n = 10;sizeof(str) = ?sizeof(p) = ?sizeof(n) = ?,sizeof(str) = 6sizeof(p) = 4sizeof(n) = 4,Page 48,内存与指针,指针的初始化 指针变量在没有被初始化之前,它的值是随机的;一个指向不明的指针是非常危险的。 当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并不分配用来存储数据的内存空间。使用指针之前,必须给它赋予一个已分配的内存地址。,Page 49,内存与指针,指针与数组举例,下列操作是否合法:int
17、 a4,*p;p = a;*(a+2) = 0 x00;p2 = 0 x01;,/等价于p=/错误a+;/错误,Page 50,内存与指针,指针与数组什么时候是相同的举例,以下为ARM平台下的一段32位C程序,请计算sizeof的值。void Func(char a100)sizeof(a) = ?,sizeof(a) = 4,(1)数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;(2)很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。,Page 51,内存与指针,数组与指针运用规则,数组,声明,使用,定义,如char a10不能写成
18、指针的形式,extern,如extern char a不能写成指针的形式,func(char a);或func(char *a)函数参数可以写成指针的形式,c = ai;或c = *(a+i);可以写成指针的形式,Page 52,C语言复习,1)循环与分支2)作用域与存储类3)内存与指针4)位操作5)预编译处理,Page 53,位操作,1)位操作的用途 硬件寄存器控制; 压缩和加密操作; 提高程序运行效率; .,因为位是程序可以操作的最小数据单位,所以理论上可以用“位操作”完成所有的运算与操作。,Page 54,位操作,2)位运算符 位逻辑运算符或flag |= MASK; 关闭位: flag
19、 = flag ,Page 57,位操作,5)用法:查看某一位的值 错误用法:if(flag = MASK) 正确用法:if(flag/00000111 unsigned char i; i = ch 2;,左移,右移,Page 59,C语言复习,1)循环与分支2)作用域与存储类3)内存与指针4)位操作5)预编译处理,Page 60,预编译处理,C编译系统在对程序进行编译之前,先进行预处理。C提供的预处理功能主要有以下三种: 宏定义 文件包含 条件编译,Page 61,预编译处理,1)宏定义 类对象宏例:#define STX 0 x02 类函数宏例:#define SQUARE(x) (x)
20、*(x) 几点说明:a.宏定义不是C语句,不在行末加分号;b.宏名有效范围为从定义处到本源文件结束;c.在宏定义时,可以引用已经定义的宏名;d.宏替换不占运行时间,只占编译时间;,Page 62,预编译处理,2)文件包含:#include 预处理器发现#include后,就会寻找后跟的这个文件并把这个文件的内容复制到当前位置替换#include指令; 使用#include指令的一些例子:,Page 63,预编译处理,3)条件编译 条件编译指不对整个程序编译,而是编译满足条件的那部分。条件编译有以下几种形式:a. #ifdef 标识符 程序段1; #else 程序段2; #endif它的作用:当
21、标识符在前面已经定义过,则对程序段1进行编译,否则对程序段2进行编译。,Page 64,预编译处理,b. #ifndef 标识符程序段1;#else程序段2;#endif它的作用和#ifdef相反,当标识符之前没被定义过,则对程序段1进行编译,否则就对程序段2进行编译。,Page 65,预编译处理,c. #if 表达式程序段1;#else程序段2;#endif它的作用:当表达式的值为真时,对程序段1进行编译,都则就对程序段2进行编译;,Page 66,预编译处理,举例,下面是某工程中.h文件中的一段程序,请说明#ifndef/#define/#endif结构的作用。#ifndefDEF_H#d
22、efineDEF_H#include #include“graphics.h”.#endif,防止头文件被重复引用,Page 67,编程规范,Page 68,编程规范,1)规范的作用 改善代码质量 提高开发速度 增进团队精神 养成良好习惯,Page 69,编程规范,2)编程规范 养成良好的编程习惯,Page 70,开发高效程序的技巧,Page 71,开发高效程序的技巧,1)ARM编程中局部变量的使用 举例,请看一面一段程序:int checksum(int *data) char i; . for(i=0;i64;i+).; .,.ADDr1,r1,#1ANDr1,r1,#0 xFFCMPr1
23、,#0 x40.,Page 72,开发高效程序的技巧,把上面的程序段将i声明为unsigned int类型,比较一下:,.ADDr1,r1,#1CMPr1,#0 x40.,ARM编程中局部变量类型的使用:char或short类型并不比int类型占用更小的寄存器空间或者堆栈空间,应尽量不要使用char或short作为局部变量,以防止做不必要的转换;除非要使用char或short的溢出归零特性,如255+1=0。,Page 73,开发高效程序的技巧,2)ARM编程中函数参数的传递 4寄存器原则(four-register rule):ARM-Thumb过程调用标准(ATPCS)定义了R0-R3四个
24、寄存器作为参数传递和结果返回寄存器,如果参数超过4个,则使用堆栈进行传递(额外的指令和慢速的存储器操作)。因为内部寄存器的访问速度要远远大于存储器,所以我们应尽量把函数的参数控制在4个以下。,Page 74,开发高效程序的技巧,r3r2r1r0,sp+8sp+4sp,图: ATPCS参数传递,Page 75,开发高效程序的技巧,3)结构体安排 举例,对下面两个结构体进行比较struct A char a; int b; char c; short d;struct B char a; char c; short d; int b;,Page 76,开发高效程序的技巧,4)C语言中的封装思想 举例,给出这样一个人机界面:,打印速度 100 ,液晶显示屏,按键,要求:以中间的按键切换液晶显示菜单,左右两个按键对当前项的值进行增减操作。,Page 77,开发高效程序的技巧,我曾经这样做:void onLeftKey() switch(currentFocus) case MENU1: menu1onLeft(); break; case MENU2: menu2onLeft(); break; . ,void onMidKey() currentFocus+; switch(currentFocus) ca
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 九年级语文上册 军事历史故事 第8课《半截蜡烛》教案 新教版(汉语)
- 水利部门干部管理办法
- 医疗设施维护联合体协议
- 云南省思茅市(2024年-2025年小学五年级语文)统编版课后作业((上下)学期)试卷及答案
- 2024年课堂实验:《青蛙写诗》教学法探讨
- 《接触网施工》课件 2.1.1 纵向测量
- 《晚春》教案设计2024:走进智能化教学
- 安川机器人IO系统培训教程:2024年深入解读
- 第47届世界技能大赛江苏省选拔赛制冷与空调项目技术工作文件
- 2023年温州市残疾人职业技能大赛-保健按摩师(脊柱按摩师)项目技术文件
- 北科大岩石力学课件李长洪1.1岩石的力学性质(qiangdu).ppt
- 供应商QPA稽核点检表(线材)
- 资质挂靠协议
- 凸函数的性质及其应用
- 标记有丝分裂百分率法计算
- HCGE2P孕三项化验单模板
- QA软件过程检查单(XXJSTZPPQAChecklist)
- BA88半自动生化分析仪维修手册
- 各系统调试报告
- 英语人称代词-物主代词-名词所有格(共4页)
- 《质量管理体系文件》ISO9001_2015_中英文对照
评论
0/150
提交评论