欢迎来到三一文库! | 帮助中心 三一文库31doc.com 一个上传文档投稿赚钱的网站
三一文库
全部分类
  • 研究报告>
  • 工作总结>
  • 合同范本>
  • 心得体会>
  • 工作报告>
  • 党团相关>
  • 幼儿/小学教育>
  • 高等教育>
  • 经济/贸易/财会>
  • 建筑/环境>
  • 金融/证券>
  • 医学/心理学>
  • ImageVerifierCode 换一换
    首页 三一文库 > 资源分类 > PPT文档下载
     

    嵌入式系统程序设计.ppt

    • 资源ID:2605968       资源大小:2.29MB        全文页数:282页
    • 资源格式: PPT        下载积分:20
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录   微博登录  
    二维码
    微信扫一扫登录
    下载资源需要20
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    嵌入式系统程序设计.ppt

    嵌入式系统程序设计,大连理工大学软件学院 嵌入式系统工程系 赖晓晨,C/C+语言摘要,C语言的历史和特点 预处理程序 位运算 函数指针 C程序的移植,一、C语言的历史和特点,C语言的历史 C语言的特点,C语言的优良特性,结构化语言,代码数据分离 包含指针特性,允许对地址操作 语法简洁紧凑,但功能强大 编程方便,运行速度快 支持分离编译,C语言的缺点,封装性不如C+,数据安全性上有缺陷 类型检查机制相对薄弱 指针的操作带来许多不安全因素 比其他高级语言较难掌握,二、预处理程序,C89规定的预处理指令有以下几条 #if #ifdef #ifndef #else #elif #endif,#define #undef #line #error #pragma #include,预处理语句的书写规则,作用:对源程序编译之前做一些处理,生成扩展C源程序 格式: “#”开头 占单独书写行 语句尾不加分号,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),宏体可缺省,表示宏名 定义过,如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,如 if(x=YES) printf(“correct!n”); else if (x=NO) printf(“error!n”); 展开后: if(x=1) printf(“correct!n”); else if (x=0) printf(“error!n”);,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,引号中的内容与宏名相同不置换,例 #define ID 1 语句printf( “ID“ ); 会输出ID,而非1,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,宏定义可嵌套,不能递归,例 #define ID ID + 1 (),引号中的内容与宏名相同不置换,例 #define DIS1 10 #define DIS2 DIS1+10 var=DIS2*2; 宏展开:var= 10+10 *2;,1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,宏定义可嵌套,不能递归,引号中的内容与宏名相同不置换,宏定义中使用必要的括号(),1. 宏定义 不带参数宏定义 一般形式: #define 宏名 宏体 功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名,宏定义可嵌套,不能递归,引号中的内容与宏名相同不置换,宏定义中使用必要的括号(),宏体可以省略,表示宏名已被定义过,/* ch3_1.c */ #include #define A int main() #ifdef A printf(“A has been definedn“); #else printf(“A has not been definedn“); #endif return 0; 输出为:“A has been defined”,即使把宏定义改为: #define A 0 输出仍旧为:“A has been defined”。,带参数宏定义 一般形式: #define 宏名(参数表) 宏体,例 #define T (m, n) m*n 相当于定义了不带参宏T,其宏体为“(m, n) m*n”,宏展开:形参用实参换,其它字符保留,例 #define T(m,n) m*n area=T(3,2); 宏展开: area=3*2;,不能加空格,带参数宏定义 一般形式: #define 宏名(参数表) 宏体,宏展开:形参用实参换,其它字符保留 宏体及各形参外一般应加括号(),例 #define T(m,n) m*n area=T(3,2); 宏展开: area=3*2;,例 #define CUBE(x) x*x*x a=4; b=6; z=CUBE(a+b); 宏展开:z=a+b*a+b*a+b; 一般写成: #define CUBE(x) (x)*(x)*(x) 宏展开: z=(a+b)*(a+b)*(a+b);,带参的宏与函数区别,Embest开发环境中的宏定义,44b.h有44B0X中各个特殊功能寄存器的宏定义, #define rBWSCON (*(volatile unsigned *)0x1c80000) #define rBANKCON0 (*(volatile unsigned *)0x1c80004) #define rBANKCON1 (*(volatile unsigned *)0x1c80008) #define rBANKCON2 (*(volatile unsigned *)0x1c8000c) #define rBANKCON3 (*(volatile unsigned *)0x1c80010) #define rBANKCON4 (*(volatile unsigned *)0x1c80014) #define rBANKCON5 (*(volatile unsigned *)0x1c80018) ,预定义宏,C89规范了五个固有的预定义宏,分别为: _LINE_:行号 _FILE_:文件名 _DATE_:日期 _TIME_:时间 _STDC_:1标准C编译器 0非标准C编译器,预定义宏,#include int main() printf(“The current file is: %sn“, _FILE_); printf(“The current line number is: %dn“, _LINE_); printf(“today is: %sn“, _DATE_); printf(“the time is: %sn“, _TIME_); if(_STDC_ = 1) printf(“this is a standard compilern“); else if(_STDC_ = 0) printf(“this is not a standard compilern“); ,/exp/pre/macro.c,功能:对源程序中的一部分内容只有满足某种条件的情况下才进行编译。,2. 条件编译,#ifdef 标识符 程序段1 #else 程序段2 #endif,形式1:,当标识符已经被定义过(使用#define),则对程序段1进行编译,否则编译程序段2。其中#else部分可以省略。,形式1(续):,#define IBM-PC 0 /*或 #define IBM-PC */ 。 #ifdef IBM-PC #define INT 16 #else #define INT 32 #endif,可以用来提高程序的可移植性,形式1(续):,#define DEBUG #ifdef DEBUG printf(“x=%d, y=%d”,x,y); #endif,可以用来调试程序,调试结束后只需将define行删掉即可,#ifndef 标识符 程序段1 #else 程序段2 #endif,形式2:,当标识符未被定义过,则对程序段1进行编译,否则编译程序段2。(与形式1正相反),#if 表达式 程序段1 #else 程序段2 #endif,形式3:,当表达式为真时,则对程序段1进行编译,否则编译程序段2。,#include #define CAP 1 int main() char string20=“I love China“; char c; int i=0; c=stringi+; while(c!='0') #if CAP if(c='a' ,形式3:(续),3. 文件包含 功能:一个源文件可将另一个源文件的内容全部包含进来 一般形式: #include “文件名” 或 #include , 直接按标准目录搜索 “” 先在当前目录搜索,再搜索标准目录 可指定路径,3. 文件包含 功能:一个源文件可将另一个源文件的内容全部包含进来 一般形式: #include “filename” 或 #include ,处理过程:预处理时,用被包含文件的内容取代该预处理命令,再把“包含”后的文件作为一个源文件编译,被包含文件内容 源文件(*.c) 头文件(*.h),宏定义 数据结构定义 函数说明等,实际上文件名也可以是C源文件,不过这不是良好的编程风格,【例3-5】文件包含一下程序包含一个完整的模块(function.c、function.h、test.c),/* funtion.h */ #ifndef _FUNCTION #define _FUNCTION void f(); #endif /* function.c */ #include void f() printf(“a example of #include.n“); ,/* test.c */ #include #include “function.h“ int main() f(); return 0; ,头文件格式,4. 其他预处理指令,#error指令强制编译器停止编译,主要用于程序调试。 #error指令的一般形式为: 编译到#error时,会显示相应字符串,#error error-message,#error举例,#define CON1 0 #define CON2 1 #define CON3 -1 int main() #if CON1 #if CON2 #error run to position1 #else #error run to position2 #endif #else #if CON3 #error run to position3 #else #error run to position4 #endif #endif ,明确程序编译位置,三、位运算,1. 位与&,运算规则: 两个位都为1,结果为1,否则为0 例如: 9&0x0c结果为8,2. 位或|,运算规则: 两个位都为0,结果为0,否则为1 例如: 9|0x0c结果为0x0d,3. 按位取反,运算规则: 1变0,0变1 用途: 使某位取反,3. 按位取反 (续),例:使某数最低位为0,int a; a=a&0xfffffffe,3. 按位取反 (续),例:使某数最低位为0,思考:有没有隐含的问题,int a; a=a&0xfffffffe,3. 按位取反 (续),例:使某数最低位为0,/* 16位机 */ int a; a=a&0xffffe /* 32位机 */ a=a&0xfffffffe,可移植性变差,3. 按位取反 (续),例:使某数最低位为0,a=a&1 /* 1能自动适应16位机以及32位机 */,解决办法,4. 按位异或,运算规则: 判断两位是否相同,同则为0,否则为1 用途: 使特定位翻转 交换两个值,不用临时变量,4. 按位异或 (续),不通过中间变量交换两个变量的值 /* ch3_7.c */ #include int main() int a=21; int b=43; a=ab; b=ba; a=ab; printf(“a=%d, b=%dn“,a, b); return 0; ,5. 左移位,运算规则: 将一个数的全部二进制位左移若干位,移出位舍弃,右侧补0 用途: 移出位没有1时,相当于乘法运算,6. 右移位,运算规则: 将一个数的全部二进制位右移若干位,移出位舍弃,左侧可能补0或者补1,视计算机系统不同而不同。 符号问题: 无符号数右移,左侧补0 有符号数视计算机系统而定:逻辑右移、算术右移,例:循环右移n位,例:循环右移n位(续),#include int main() unsigned a,b,c,n; scanf(“a=%x,n=%d“, ,输入: a=0x12345678,n=8,显示: a=12345678,c=78123456,四、函数指针,每一个函数模块都有一个首地址,称为函数的入口地址。 指向函数的指针称为函数指针,保存的是函数的入口地址(首地址) 函数调用:找到函数入口地址;传递参数,1. 函数指针的定义方法,格式:int (*ptr1)(int); 定义了函数指针ptr1,此指针只能保存具有一个整型参数的整型函数的首地址。 注意 : int *ptr1(int); 这是一条函数声明语句,表示一个带有整数参数的函数返回,返回一个整型指针。 int (*ptr1)(int); 这个是函数指针,例:,以0.1为步长,计算特定范围内的三角函数之和。,sin(0.1)+sin(0.2)+sin(1.0) cos(0.5)+cos(0.6)+cos(3.0),#include #include double triangle(double(*func)(double), double begin, double end) double step,sum=0.0; for(step=begin;stepend;step+=0.1) sum+=func(step); return sum; int main() double result; result=triangle(sin, 0.1, 1.0); printf(“the sum of sin from 0.1 to 1.0 is %fn“,result); result=triangle(cos, 0.5, 3.0); printf(“the sum of cos from 0.5 to 3.0 is %fn“,result); return 0; ,#include #include double triangle(double(*func)(double), double begin, double end) double step,sum=0.0; for(step=begin;stepend;step+=0.1) sum+=func(step); return sum; int main() double result; result=triangle(sin, 0.1, 1.0); printf(“the sum of sin from 0.1 to 1.0 is %fn“,result); result=triangle(cos, 0.5, 3.0); printf(“the sum of cos from 0.5 to 3.0 is %fn“,result); return 0; ,2. 用typedef来简化函数指针,对参数较多的函数类型,定义相应的函数指针比较烦琐,可用typedef关键字简化 例如 typedef double (*FUN)(double a, double b);,用typedef来简化函数指针(续),格式:int (*ptr1)(int); 定义函数指针的别名方法: 定义了函数指针ptr1,此指针只能保存具有一个整型参数的整型函数的首地址。,double (*fun1)(double a, double b); typedef double (*FUN)(double a, double b); FUN f1; FUN f2;,用typedef来简化函数指针(续),格式:int (*ptr1)(int); 定义函数指针的别名方法:(也可以这样) 定义了函数指针ptr1,此指针只能保存具有一个整型参数的整型函数的首地址。,double (*fun1)(double a, double b); typedef double (FUN)(double a, double b); FUN *f1; FUN *f2;,3函数指针数组,声明方式 定义了表示定义了一个长度为4的函数指针数组,同时做了初始化。,double ( * fp4 ) (double,double)= f1 , f2 , f3, f4 ,4函数指针应用,在嵌入式操作系统中,经常用函数指针来完成任务的调度。 例如uC/OS中,任务创建的函数原型为 第一个参数为函数指针,INT8U OSTaskCreate(void(*task)(void*pd), void *pdata, OS_STK *ptos, INT8U prio);,五、C程序的移植,为一种机器写的程序,经常需要在其他硬件、操作系统的平台上运行,往往需要对此程序进行一些改动,这个过程叫做程序的移植 方便移植的程序称为可移植程序 程序不可移植,主要是因为有太多硬件相关的代码,1、避免使用“魔数”,“魔数”(magic number):依赖于系统或处理器的数字。例如表示硬盘缓冲区的大小、屏幕和键盘的特定尺寸等数字。 “魔数”的出现使系统可移植性变差。下列代码本质上是不可移植的,fread(buf, 256, 1, fp); /缓冲区为256B,使用#define替换“魔数”,程序中要尽量避免“魔数”的硬编码,可以用宏来取代魔数,使可读性增强,而且移植程序时只要修改宏一处即可,#define BUFFER_SIZE 256 fread (buf, BUFFER_SIZE, 1, fp);,例,一个图形处理程序中,需要不同的颜色执行不同操作,例,/*恶劣的例子*/ void ShowColor(int color) if ( color = 0 ) sub_red(); else if ( color = 1 ) sub_blue(); else if ( color = 2 ) sub_green(); return ; ,例(改进后的程序),/*然后在源文件中直接使用这些宏来判断*/ #include “color.h“ void ShowColor(int color) if ( color = RED ) sub_red(); else if ( color = BLUE ) sub_blue(); else if ( color = GREEN ) sub_green(); return ; ,/* color.h*/ #define RED 0 #define BLUE 1 #define GREEN 2,2、程序分层,不同的操作系统为应用程序提供了不同的支持,例如windows2000应用程序可以有多线程特性,但是windows3.2不可以,应用程序对系统有依赖型。 这种依赖性没有具体通用的解决方法,但是可以通过程序分层来解决,把系统相关的代码放到一起。,3、注意数据类型的长度,16位机中整型数据是2字节,32位机为4字节,这会导致程序的不兼容。 可以利用宏来重定义数据类型,#define int16 int /16位机 int16 a;,#define int16 short int /32位机 int16 a;,注意数据类型的长度(续),16位机中整型数据是2字节,32位机为4字节,这会导致程序的不兼容。 使用可适应任何情况的编码方式,例如把一个整型数据写入磁盘:,fwrite( /好,4、对齐问题,某些计算机允许数据边界地址不对齐,把这样的代码移植到ARM上时要小心。 ARMv5TE前的处理器都不支持地址不对齐的指针,5、大小端问题,如果两台计算机的大小端定义不一致,那么代码移植时要做转换,6、枚举类型,enum是可移植的,但是不同编译器中对enum分配的字节数可能不同。 不能在不同的编译器之间对代码进行交叉连接,7、减少内嵌汇编,C语言的内嵌汇编由C编译器来负责编译,而不使用armasm或gas。内嵌汇编可以提高编程效率,但是会影响到程序的可移植性。,C语言与C+语言的区别,变量定义位置 结构体变量 数据类型 输入输出 动态内存分配 其他区别,1. 变量定义位置,C89要求所有变量都必须定义在块的最前部 C+没有这个要求,可以在程序任意位置定义新的变量,2. 结构体变量,在C+中,struct结构体支持成员函数的定义,C中不行。 如果在C的struct中定义函数,编译时会显示一个“field function name declared as function”错误,2. 结构体变量(续),/* ch3_10.c */ struct A int a; int b(); ; int main() struct A c; c.a=2; return 0; 编译错误:“ch3_10.c:5: error: field 'b' declared as a function” C+标准可以通过编译,2. 结构体变量(续),在C语言中,声明一个结构体类型A之后,使用下面的语句来定义结构体变量a: struct A a; 而C+语言中可以省略struct,3. 数据类型,C+中有bool (或boolean类型); C中没有这样的bool类型,均为数值类型! C编译器不能通过编译,C+编译器可以,bool a; a = 1;,4. 输入输出,C中使用printf、scanf输入输出 使用时不用包含任何头文件 但如果使用g+编译时必须加上stdio.h头文件,int a; scanf( “%d“, ,A. scanf()函数,功能: 从键盘读入指定格式的数据 格式: scanf( “控制字符串“, 输入项列表 ); 注意: scanf中各变量一定是表示地址的标识符(加&),控制字符串,控制字符串有两部分组成: 格式说明 形式: % 普通字符 空格 可打印字符,格式说明,各格式字符及其意义:(详见C教程) d:输入一个十进制整数 o:输入一个八进制整数 x:输入一个十六进制整数 f:输入一个小数形式的浮点数 e:输入一个指数形式的浮点数 c:输入一个字符 s:输入一个字符串,空格,在多个输入时,一般用空格或回车作为分隔符 若以空格作为分隔符,当输入中包含字符类型时,可能产生非预期的结果,scanf ( “%d%c“, 输入:45 q 输出:45 空格,空格(续),如下语句会有正确输出 此处%d后的空格,就可以跳过字符'q'前的所有空格,scanf ( “%d %c“, 输入:45 q 输出:45 q,可打印字符,看一个例子 输入为:1,2,q 可以得到 a = 1, b = 2, ch = q 输入为:1 2 q 除a的值为1外,对b与ch的赋值失败,scanf ( “%d,%d,%c“, ,B. printf()函数,功能: 从缺省输出设备(一般为显示器)输出规定格式的字符串 格式: printf( “控制字符串“, 输入项列表 );,控制字符串,控制字符串有两部分组成: 格式说明 形式: % 普通字符 空格 可打印字符,格式说明,各格式字符及其意义:(详见C教程) c:按字符型输出 o:按八进制输出 d:按十进制输出 x:按十六进制输出 u:按无符号整数输出 f:按浮点型小数输出 g:按e和f格式中较短的一种输出 e:按科学计数法输出,普通字符,普通字符: 可打印字符 主要是说明字符,按原样输出,支持汉字输出 转义字符(例) 不能直接打印,控制产生特殊的输出效果,普通字符(续),转义字符示例,i = 789,n = 123, a = 92.34567,且i为整型,n为长整型。 printf( “%4dt%7.4fnt%lun“, i, a, n ); 输出为: 789 92.3457 123,C语言输入输出总结,输入输出可能是C和C+的最明显的区别 C中用scanf(), printf()来完成输入输出操作 C+中全局对象cin、cout来输入输出,比C更方便,而且类型检查机制更加完善,C+中的使用方式 new 申请 delete 释放 C中的使用方式 malloc() 申请 free() 释放,5. 动态内存分配,函数原型: void *malloc( long size ); 作用: 在对内存中分配size各字节,并返回了指向这块内存首地址的指针 如果分配失败,返回NULL 返回指针为void*型的,要强制转换,A. malloc()函数,函数原型: void free( void *FirstByte ); 作用: 将之前用malloc申请的空间归还操作系统 否则就导致内存泄漏 编译器不会发现内存泄漏这样的错误,B. free()函数,C. 函数的用法,/* 例 3-11 */ #include #include int main() int* p; if(p = (int*)malloc(sizeof(int) = NULL ) printf(“动态内存分配失败n“); exit(1); ,C. 函数的用法(续),*p = 100; printf(“%dn“, *p); free(p); p = NULL; return 0; ,头文件: malloc和free被头文件stdlib.h包含 C+中new和delete为关键字,故无需头文件包含 使用: int *p=(int*)malloc(sizeof(int); int *p = new int;,与C+的几点区别,6. 其他区别,常量表示方法不同 C语言不支持引用的概念,而C+支持 注释不同,C89不支持单行注释 (+i)+在C中不合法 (a=3)=4在C中不合法 不能在for循环头部定义变量,GNU C扩展,64位整型数据类型 内联函数 attribute关键字 单行注释,switch case 简写 预定义宏 结构体和初始化 长度为0的数组,64位整型数据类型,GNU CC(GNU Compiler Collection)定义了64为整型关键字“long long“,可以直接操作64位数据,long long int a = 0x123;,expgnu_clong.c,内联函数,减少函数调用开销 增加类型检查,比宏使用更安全 inline是建议而非命令,attribute关键字,关键字attribute通过向GCC指明有关代码的更多信息来帮助代码优化工作进行的更好。,attribute关键字(续),下面代码通过使用_attribute_,当t未被使用时编译器不会警告,int main( ) float t _attribute_ (unused); return 0; ,例3-12,#include void quit() _attribute_ (noreturn); void quit() exit(1); int test(int n) if ( n 0 ) quit(); else return 0; ,int main( ) test(1); return 0; ,函数不返回,【例3-13】,/* ch3_13.c */ #include struct s int a2 _attribute_ (aligned (8); ; struct t char a; int b2 _attribute_ (packed); ;,int main() int y _attribute_ (aligned (16); y=1; return 0; ,以8字节对齐,单行注释,int main() /long long t1; int t4=3; return 0; ,expgnu_cnote.c,switch case 简写,/* ch3_14.c */ #include int main() int t=2; /*传统方式*/ switch(t) case 0 : case 1 : case 2 : printf(“012n“); break; case 3 : case 4 : case 5 : printf(“345n“); ,switch case 简写,/*GCC扩展方式*/ switch(t) case 0 . 2 : printf(“012n“); break; case 3 . 5 : printf(“345n“); return 0; ,expgnu_ccase.c,gcc允许这样写。,预定义宏,/* ch3_15.c */ #include void f(void) printf(“This is function %s n“, _FUNCTION_); int main( ) printf(“This is function %s n“, _FUNCTION_); f(); return 0; ,expgnu_cfunc.c,结构体初始化,struct file_operations ext2_file_operations = llseek: generic_file_llseek, read: generic_file_read, write: generic_file_write, ioctl: ext2_ioctl, mmap: generic_file_mmap, open: generic_file_open, release: ext2_release_file, fsync: ext2_sync_file, ;,expgnu_cfunc.c,结构体初始化,struct file_operations driver_fops = owner : THIS_MODULE, read : driver_read, open : driver_open, release : driver_release, ; 其他的值被初始化为0.,expgnu_cfunc.c,长度为0的数组,GNU还允许结构体的末尾成员是长度为0的数组,错误处理机制,C语言错误处理机制 系统日志文件,一、C语言的错误处理机制,C标准中有几个错误处理机制 预定义宏 预定义全局变量 若干库函数,1. assert宏,assert宏定义在assert.h中 语法格式: 作用: 计算表达式expression的值,如果为0,那么首先向stderr打印一条出错信息,然后调用abort()函数终止程序运行。,assert (expression),【例3-16】,/* ch3_16.c */ #include #include #include int main() char *p; p = getenv(“HOME“); assert(p); printf(“HOME=%sn“,p); p = getenv(“NOTEXIST“); assert(p); printf(“NOTEXIST=%sn“,p); return 0; ,/exp/error/badptr.c,assert的缺点,assert的调用会影响程序的运行效率,有时希望程序中的assert不会起作用,这可以通过在程序前部包含assert.h之前定义一个 NDEBUG来实现。,【例3-17】,/* ch3_17.c */ #define NDEBUG #include #include #include int main() char *p; p = getenv(“HOME“); assert(p); printf(“HOME=%sn“,p); p = getenv(“NOTEXIST“); assert(p); printf(“NOTEXIST=%sn“,p); return 0; ,/exp/error/badptr2.c,assert使用注意事项,当使用#define NDEBUG来禁用assert宏时,注意assert宏中隐含的某些操作不能完成,而这些代码可能对后面的操作有关键作用。,定义NDEBUG,p赋值行未执行,使用p时出错。,assert使用注意事项举例,#define NDEBUG assert(p=malloc(sizeof(char)*100); free(p);,#define NDEBUG p=malloc(sizeof(char)*100); assert(p); free(p);,应该按照这种方式来编写,P是野指针,assert使用讨论,assert宏只提供了一种粗糙的终止程序运行的方式,这种方法并不理想。 理想的方式是“适

    注意事项

    本文(嵌入式系统程序设计.ppt)为本站会员(本田雅阁)主动上传,三一文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    经营许可证编号:宁ICP备18001539号-1

    三一文库
    收起
    展开