C语言软件编程经验交流ppt课件_第1页
C语言软件编程经验交流ppt课件_第2页
C语言软件编程经验交流ppt课件_第3页
C语言软件编程经验交流ppt课件_第4页
C语言软件编程经验交流ppt课件_第5页
已阅读5页,还剩63页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.,1,报告人:吴宪云2018.10.21,C语言软件编程之经验交流,西安电子科技大学,.,2,这次报告比较局限于C语言,不会讲太多其他高级语言比如C+,JAVA,PYTHON等等,刚进实验室的学生我的建议是先学好C语言,掌握项目开发中软件的开发目的,开发流程,测试流程等。注意,做这个报告的目的是希望大家能够开发出高效的C程序,而不是让大家开发出复杂高难度高技巧的C程序。,报告目的,.,3,提纲,一、C语言基础二、内存管理三、常用技巧四、调试五、示例,.,4,开发软件,工欲善其事,必先利其器-论语牢牢打好基础,紧紧抓住核心,真正实现目的-深入学习科学发展观,编辑软件:VC+6.0,VS20XX编程辅助软件:msdn功能性辅助软件:vcassistant,numegaboundschecker,intelvtune,sourceinsight推荐的资料:高质量C/C+编程指南(林锐)、Windows核心编程、linux高级程序设计,.,5,一、C语言基础,在C语言中使用的词汇分为六类:标识符,关键字,运算符,分隔符,常量,注释符。,1.1.1C语言词汇,.,6,标识符只能是字母、数字、下划线组成的字符串,并且其第一个字符必须是字母或下划线。以下标识符是合法的:a,x,_3x,BOOK_1,sum5以下标识符是非法的:3s以数字开头;s*T出现非法字符*;-3x以减号开头;,(1)标识符,一、C语言基础,.,7,在使用标识符时注意以下几点:标准C不限制标识符的长度,但它受各种版本的C语言编译系统限制,同时也受到具体机器的限制;在标识符中,大小写是有区别的。例如BOOK和book是两个不同的标识符;标识符虽然可由程序员随意定义,但标识符是用于标识某个量的符号。因此,命名应尽量有相应的意义,以便阅读理解,作到“顾名思义”。intImgWidth;,(1)标识符,一、C语言基础,.,8,1、匈牙利命名法:开头字母用变量类型的缩写,其余部分用变量的英文或英文的缩写,要求单词第一个字母大写。intiMyAge;“i”是int类型的缩写;charcMyName10;“c”是char类型的缩写;floatfManHeight;“f”是float类型的缩写;2、驼峰规则:又叫小驼峰式命名法。第一个单词首字母小写,后面其他单词首字母大写。intmyAge;charmyName10;floatmanHeight;3.帕斯卡命名法:又叫大驼峰式命名法。每个单词的第一个字母都大写。intMyAge;charMyName10;floatManHeight;,一、C语言基础,.,9,关键字是由语言规定的具有特定意义的字符串,通常也称为保留字。用户定义的标识符不应与关键字相同。C语言的关键字分为以下几类:,(2)关键字,一、C语言基础,类型说明符用于定义、说明变量、函数或其它数据结构的类型。如char,short,int,double等语句定义符用于表示一个语句的功能。如for,if,else,while,switch等。预处理命令字用于表示一个预处理命令。如#define#pragma等。,.,10,C语言中运算符与变量,函数一起组成表达式,表示各种运算功能。运算符由一个或多个字符组成,如,=,C语言中的常量是不接受程序修改的固定值。,(6)注释符,C语言的注释符是以“/*”开头并以“*/”结尾的串,C+中使用“/”注释所在行。,一、C语言基础,.,12,什么是字节对齐,为什么要字节对齐?,1.1.2字节对齐,一、C语言基础,.,13,(1)什么是字节对齐?,现代计算机中内存空间都是按照byte划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。,一、C语言基础,.,14,(2)为什么要字节对齐?,对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。,一、C语言基础,.,15,(3)大小端(例程),在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。对于位数大于8位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。,所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,一、C语言基础,.,16,(3)大小端(例程),写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1,intcheckCPU()unionwinta;charb;c;c.a=1;return(c.b=1);,一、C语言基础,.,17,(3)大小端(例程),采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节序是所有成员都从低地址开始存放。联合体union的存放顺序是所有成员都从低地址开始存放。,一、C语言基础,.,18,/作者版权版本说明,头文件声明,全局变量,函数声明,预处理块#include#include”global.h”voidoutput();/子函数声明intmain(intargc,char*argv)inti,j;unsignedchar*data;/定义局部变量/分配数据空间,分配在堆上data=(unsignedchar*)malloc(1000*sizeof(unsignedchar);for(i)/调用子函数output();/释放分配空间free(data);data=NULL;voidoutput(),一、C语言基础,.,19,#ifndefGRAPHICS_H(作用:防止graphics.h被重复引用)#defineGRAPHICS_H#include.(作用:引用标准库的头文件)#include.(作用:引用非标准库的头文件)voidFunction1(.);(作用:全局函数声明)classBox(作用:类结构声明);#endif,1.2.1头文件,一、C语言基础,.,20,在头文件中,用ifndef/define/endif结构产生预处理块,用#include格式来引用库的头文件。头文件一般由三部分内容组成:,1.2.1头文件,头文件开头处的版权和版本声明;预处理块;函数和类结构声明等。,一、C语言基础,.,21,头文件的主要作用在于调用库功能,对各个被调用函数给出一个描述,其本身不包含程序的逻辑实现代码,它只起描述性作用,告诉应用程序通过相应途径寻找相应功能函数的真正逻辑实现代码。用户程序只需要按照头文件中的接口声明来调用库功能,编译器会从库中提取相应的代码。,1.2.1头文件,一、C语言基础,.,22,注意:1)在.h文件中声明的函数,如果在其对应的.c文件中有定义,那么我们在声明这个函数时,不使用extern修饰符,如果反之,则必须显示使用extern修饰符;2)不要在.h文件中编写实现代码,不要#include“.c”文件。,1.2.1头文件,一、C语言基础,.,23,所有全局变量尽量以g_开头,并且尽可能声明成static类型;尽量杜绝跨文件访问全局变量.如果的确需要在多个文件内访问同一变量,应该由该变量定义所在文件内提供GET/PUT函数实现;全局变量必须要有一个初始值,全局变量尽量放在一个专门的函数内初始化;如调用全局变量的函数少于三个,考虑改为局部变量实现。,1.2.2谨慎使用全局变量,一、C语言基础,.,24,在实际的软件项目中,每个人负责的可能只是一个模块,对全局变量的使用没有小程序那样简单,在使用全局变量的时候更要谨慎,跨模块调用的全局变量使用时都需要申请,而且定义必须明确。,1.2.2谨慎使用全局变量,一、C语言基础,.,25,voidmain(intargc,char*argv),1.2.3main函数,一、C语言基础,命令行界面的程序,通常都需要输入命令行参数帮助程序执行。假定有一个可执行程序名为test.exe。运行该程序的的命令行如下:test.exe带命令行参数是同一行中的附加项:test.execTEST其中c和TEST就是命令行参数。C程序通过使用main()的参数来读取这些附加参数。,.,26,main(intargc,char*argv)这个函数中两个参数的意义:argc记录的是命令行中输入参数的数目;argv是一个拥有argc个元素的字符串数组,每个元素保存一个命令行中输入的参数。,1.2.3main函数,一、C语言基础,.,27,#includeintmain(intargc,char*argv)inti;for(i=0;iargc;i+)printf(Argument%dis%s.n,i,argvi);return0;,1.2.3main函数,一、C语言基础,下面的程序演示argc和argv的使用:,.,28,Argument0ishello.exe.Argument1isa.Argument2isb.Argument3isc.Argument4isd.Argument5ise.,1.2.3main函数,一、C语言基础,运行结果:,假如上述代码编译为hello.exe,那么运行:hello.exeabcde,.,29,1.2.3main函数,一、C语言基础,在这个例子中,argc的值为6,命令行一共输入了六个参数:“hello.exe”、“a”、“b”、“c”、“d”、“e”对应程序输入为:argv0:repeat.exe,argv1:a,argv2:b,argv3:c,argv4:dargv5:e,需要注意的是若输入参数作为数值使用时,使用atoiatof进行字符转换看例程,.,30,一、C语言基础,1.3代码编写规范,从书写清晰,便于阅读,理解,维护的角度出发,在书写程序时应遵循以下规则:,一个说明或一个语句占一行。if,for,while,do占一行,执行语句放后面并且使用大括号,多用对齐。用括起来的部分,通常表示了程序的某一层次结构。一般与该结构语句的第一个字母对齐,并单独占一行。低一层次的语句或说明可比高一层次的语句或说明缩进若干格后书写。以便看起来更加清晰,增加程序的可读性。在编程时应力求遵循这些规则,以养成良好的编程风格。多写注释,合理的使用注释可以让你的程序可读性更高。,.,31,一、C语言基础,另外一些编程风格说明:,程序块要采用缩进风格编写,缩进少使用空格键;对齐多使用TAB键,少使用空格键;逗号、分号只在后面加空格。inta,b,c;比较操作符,赋值操作符“=”,“+=”,算术操作符“+”,“%”,逻辑操作符“,char*p;,0 x123456,假设已给p分配空间0 x123456p=0 x123456i=200,0 x123456,0 x123452,100,*p=100,0 x201212,0 x201216,/分配到0 x123456,存储在栈地址0 x201216的内存地址中*p=100;/修改0 x123456中数值为100/free将分配的动态内存区域释放free(p);/虽然0 x123456该地址被标志为已释放,但是p内存储的仍然是0 x123456,p成为野指针p=NULL;/将0 x201216内数据改为0 x00,该地址不可访问,malloc与free:,.,44,二、内存管理,当子函数中使用指针时,子函数执行结束指针没有free掉,此时指针变量释放了,不代表它所指向的内存自动释放了。当内存被释放时,不代表指针不存在了或者指针成为NULL指针。需要查找程序内存泄漏。,2.3指针,需要注意的几点:,.,45,三、常用技巧,3.1宏的使用,#defineceil_div(x,y)(x+y-1)/y,宏执行的是简单的替换作用,需要注意由操作符优先级引起的问题,多加括号。,那么a=ceil_div(b为了避免这种情况发生,应当多写几个括号:#defineceil_div(x,y)(x)+(y)-1)/(y),.,46,三、常用技巧,3.1宏的使用,函数变宏,每行代码最后都加行连接符“”,即使是空行也要加“”,最后一行代码后面不需要加“”,每行“”最后不能有多余字符或者空格,返回的是最后一条语句的执行结果。可以在宏函数内定义变量,可以使用if等语句,可以在宏内调用其他宏,可以使用指针。函数变宏可以加快程序运行速度。看例子,.,47,三、常用技巧,3.2运行时间测量,程序运行过程中,我们经常需要统计程序运行时间。下面给出示例:,#includemain()clock_tbegin,end;begin=clock();end=clock();doubleduration;duration=(double)(end-begin)/CLOCKS_PER_SEC;printf(“Timeis%2.1fsecondsn,duration);/#defineCLOCKS_PER_SEC1000/事实上endbegin获得的是毫秒计数,.,48,三、常用技巧,3.2运行时间测量,Time()函数是获得当前系统时间用的,一般不用于计时。当程序运行时间太短时,可以使用多次执行的办法来获得。可以使用更精确的运行时间计数函数:“QueryPerformanceCounter()”“QueryPerformanceFrequency()”,.,49,三、常用技巧,随机数生成:,#include#include#includevoidmain(void)inti;/*Seedtherandom-numbergeneratorwithcurrenttimesothat*thenumberswillbedifferenteverytimewerun.*/srand(unsigned)time(NULL);/*Display10numbers.*/for(i=0;i10;i+)printf(%6dn,rand();,Srand是产生伪随机序列的种子,种子一样产生的伪随机序列一样。RAND_MAX0 x7fffffffj=(int)(*rand()/(RAND_MAX+1.0)产生一个0到之间的随机数,.,50,三、常用技巧,3.3文件操作,文件的打开与关闭文件在进行读写操作之前要先打开,使用完毕要关闭。打开文件实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其它操作。关闭文件则断开指针与文件之间的联系,也就禁止再对该文进行操作。在语言中,文件操作都是由库函数来完成的。fp=fopen(“filename”,“r”);,.,51,三、常用技巧,对于文件使用方式有以下几点说明:文件使用方式由r,w,a,b,t,+六个字符拼成,各字符的含义是:r(read):读w(write):写a(append):追加b(binary):二进制文件+:读和写凡用“r”打开一个文件时,该文件必须已经存在,且只能从该文件读出。用“w”打开的文件只能向该文件写入。若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件。,.,52,三、常用技巧,if(fp=fopen(“readme.txt,rb)=NULL)printf(nerroronopenc:hzk16file!);exit(1);,若要向一个已存在的文件追加新的信息,只能用“a”方式打开文件。但此时该文件必须是存在的,否则将会出错。在打开一个文件时,如果出错,fopen将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作,并作相应的处理。,.,53,三、常用技巧,文件的读写对文件的读和写是最常用的文件操作。在语言中提供了多种文件读写的函数:字符读写函数:fgetc和fputc字符串读写函数:fgets和fputs数据块读写函数:fread和fwrite格式化读写函数:fscanf和fprinf行操作。,.,54,三、常用技巧,文件的读写在文件内部有一个位置指针,用来指向文件的当前读写字节。在文件打开时,该指针总是指向文件的第一个字节。使用fgetc函数后,该位置指针将向后移动一个字节。应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的,文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针系统自动向后移动。,.,55,三、常用技巧,计算文件长度的程序示例,longfilesize(FILE*stream)longcurpos,length;curpos=ftell(stream);fseek(stream,0L,SEEK_END);length=ftell(stream);fseek(stream,curpos,SEEK_SET);returnlength;,进行二进制文件读写时,打开方式后面加“b”,.,56,四、调试,编程出现error时,从第一个error处开始解决错误,可能是很小的书写错误引起的。warning也需要关注,有时候会导致程序运行错误发生。程序出现BUG时,单步跟踪,查看变量,查看内存,查看栈调用,可以边编辑边跟踪。加入合适的断点,使用条件断点。程序调试结束后需要查找内存泄露,规范代码书写。使用assert,只有条件满足才继续向下执行,在release下不会编译该语句。,程序编写完成不一定是完全正确的,需要进行测试并进行跟踪调试。,.,57,四、调试,4.1条件断点,我们在调试的时候希望程序在某个断点处只有在满足一定的条件下中断,在不满足条件的时候正常运行,可以为程序调试带来极大的便利。示例,.,58,四、调试,4.2内存泄漏查找,养成好的代码写作规范,掌握内存管理概念,减少不规范代码内存泄漏可能性。是否内存泄露:运行可执行文件,使用任务管理器查看内存占用情况是否一直增加。比较简单但是显示不一定精确。使用NumegaBounderChecker软件查找,程序中加入exit(0)强制中断,Debug至该代码行程序异常中断时查看内存泄露报告。示例,.,59,四、调试,4.3watch,跟踪调试时多使用watch窗口,在watch窗口内可以进行有限运算,注意watch运算带来的影响。示例,.,60,四、调试,4.4C程序优化,首先要确定优化目标,然后寻找优化方法。查找程序运行瓶颈,使用IntelVtune查看各部分运行时间,一步步进行优化。现在CPU,GPU发展方向都是多核,并行计算越来越方便,为优化提供了更多解决方案。,任务级并行,使用多线程发挥多核优势。指令级并行,使用MMX,SSE,SSE2等指令集。参看Vtune使用指南,.,61,五、示例,5.1软件设计,算法思想,思路清楚,注意细节质量控制,代码高效,风格良好测试调试,测试全面,调试认真,软件设计过程关键部分:,在编写软件程序之前,首先要明确你要解决的问题,软件只是思想的实现,不能通过编程来获得思想。所以在编写之前就需要对问题有透彻的理解,对解决问题的方法有清晰的思路,要考虑到可能遇到的所有问题,同时要考虑到软件的可靠性稳定性等。,.,62,五、示例,5.1软件设计,在编写软件程序之前,首先要明确你要解决的问题,软件只是思想的实现,不能通过编程来获得思想。所以在编写之前就需要对问题有透彻的理解,对解决问题的方法有清晰的思路,要考虑到可能遇到的所有问题,同时要考虑到软件的可靠性稳定性等。在代码编写的时候,注意代码编写规范,编写风格良好的代码,多用注释让代码的可读性变高。实际上一个项目中代码编写的时间可能是最短的。前期算法的测试和后期测试工作占得时间更多。代码编译通过不代表软件完成,代码编写完成后需要进行大量的测试来确保程序的正确性,这也要求代码编写的适合大规模测试。在遇到问题的时候首先思考下算法设计是否合理,重新考虑下软件编写思路是否还有没有考虑到的情况,然后对代码进行跟踪调试。,.,63,五、示例,5.2VC6+的使用,创建程序添加程序文件编写代码编译运行设置参数调试程序,.,64,五、示例,5.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论