1、开源代码分析C/C+语言介绍语言介绍1C/C+的实现nC/C+在现代数字计算机上的实现n各种语法映射到实际硬件实现n高效地实现语言的各项特性n提供一定的资源管理能力n提供方便开发的工具、库2C/C+的实现n平坦地址空间模型n所有数据、代码共享一个地址空间n便于操作系统管理和分配内存n程序需要存储哪些信息?n函数n各个函数的指令n数据n全局变量,静态变量,局部(自动)变量n动态分配的存储空间,函数调用信息n如何实现这些功能和信息?n必须要清楚各自的功能和特点3C/C+的实现n局部(自动)变量n仅在定义变量的函数被调用时存在n当函数被递归调用时,可有多个不同变量float pow(float x,
2、int n)if(n=1)return x;if(n=0)return 1;int t=n/2;return pow(x,t)*pow(x,n-t);pow(0.5,3)void main()pow(0.5,5);main()x=?n=?t=?x=0.5 n=3 t=1pow(0.5,1)pow(0.5,2)x=0.5 n=1 t=?x=0.5 n=2 t=1pow(0.5,1)pow(0.5,1)4C/C+的实现n全局变量n程序的整个生存周期都存在n常量和全局资源的管理数据const char*FlagToName=“create”,“open”,“append”;同步地把Root换成thi
3、s(多线程安全)volatile:如一个变量可能被多个线程修改,应定义为volatilethis:C+成员函数中指向当前对象的指针5C/C+的实现n静态变量n程序的整个生存周期内存在n当函数被递归调用时,也仅有一个变量float pow(float x,int n)static int entryCount=0;entryCount+;void main()pow(0.5,5);pow(0.5,3)main()entryCount=0entryCount=1pow(0.5,1)pow(0.5,2)entryCount=2entryCount=3pow(0.5,1)pow(0.5,1)大多数静态
4、变量可以用类变量代替6C/C+的实现n可重入和不可重入代码n可重入n多个线程调用同一个函数,结果不会出问题n可能影响重入的因素n使用全局变量n使用静态局部变量n使用类成员变量n类成员函数一般是不可重入的!n调用了不可重入函数的函数可能是可重入的!n使用了除局部变量以外的任何变量7C/C+的实现n可重入和不可重入代码n不可重入代码不一定只影响多线程出现n如果大量使用全局变量,这些变量表征的对象在一个程序中只能有一个n把所有变量和函数封装成一个类即可解决car.cppchar*CarBrand=“Red Flag”;int CurSpeed=0;bool Start()8C/C+的实现n动态分配的
5、存储空间n生存周期由程序员控制n可能跨越函数,也可能仅跨越几条语句n函数调用信息(返回地址等)n与局部变量相同n函数n程序的整个生存周期内存在n与各种数据都很不相同n与常量有一定相似性9C/C+的实现n各种信息总结n程序的整个生存周期内存在n函数,全局变量,静态变量n仅在定义变量的函数被调用时存在n局部变量,函数调用信息n由程序员控制n动态分配的存储空间n各部分应分别管理,放置在地址空间的不同部位10C/C+的实现n程序在内存中的映象未映射空间函数数据栈操作系统的代码、数据00000000FFFFFFFF开始执行位置文件头函数1函数n_startupmain()call _maincall _
6、exit函数在内存的顺序并不重要全局和静态数据的实现没有区别防止空指针错误堆11C/C+的实现n栈n管理函数调用和返回,分配局部变量n为什么用栈?n函数可以递归调用n栈指针n指向栈顶部的指针n栈框架n一个函数的调用信息、局部变量等所有的信息Test()SFSPmain()SFGo()SFprintf()SF已分配空间未分配空间不能返回指向局部变量的指针或引用!12int*ptr()int y=3;return&y;main()int*SA,content;SA=ptr();content=*SA;printf(%d,content);/*?*/content=*SA;printf(%d,con
7、tent);/*?*/;mainSA(?)ptry(3)SPmainSASPmainSAprintfSPC/C+的实现13C/C+的实现n栈n一般不太大(1MB或以下)n大块的内存应该程序员主动管理,不应自动管理n不要定义大的局部数组n堆n程序员主动管理的内存n主要的存储资源14C/C+的实现n堆n易犯的错误typedef struct TMyStruct;TMyStruct*sptr=(TMyStruct*)malloc(n*sizeof(TMyStruct*);struct TMyStruct;TMyStruct*sptr=new TMyStruct*;这个*是不能有的编译没有问题编译报错
8、CC+15C/C+的实现n堆n易犯的错误n假设变量大小int*dynArray=(int*)malloc(mySize*4);n尽量用sizeof计算变量的大小n特别是结构的大小n结构的大小在不同的编译选项下面可能有差异16C/C+的实现n变量的对齐方式struct TMyStructchar c;int i;sizeof(TMyStruct)=?如果假设:sizeof(int)=4 sizeof(char)=1,sizeof(TMyStruct)=?17C/C+的实现n变量的对齐方式一个字ci一个字cisizeof(TMyStruct)=5sizeof(TMyStruct)=8填充sizeo
9、f(int)=4 sizeof(char)=118C/C+的实现n变量的对齐方式iiCPU19C/C+的实现n变量的对齐方式nn(n=(1x)字节大小的变量,其首地址应该是n的倍数n任何变量,其首地址是m(m=(1 .objn.obj:函数、引入符号表、引出符号表n高级语言函数“翻译”成机器语言函数n但是n.obj不能执行n尚未解决的地址n如何让程序执行起来?43C/C+的实现n函数的地址和函数指针n连接器n一个程序要调用多个函数n编译器生成多个独立的函数n连接器把函数合并到一起成为程序44C/C+的实现n函数的地址和函数指针n连接器_startup0 x00001234:_main0 x00
10、005678:_exit_startup0 x00010000?45C/C+的实现n函数的地址和函数指针n连接器_startup0 x00010000_main0 x0000abcd:_printf_exit_main_exit?0 x0001abcd0 x0001ef0146C/C+的实现n函数的地址和函数指针n连接器_startup0 x00010000_main_exit0 x0001abcd0 x0001ef01_printf_printf?47C/C+的实现n函数的地址和函数指针n经常使用的函数n每次都重新编译?n放到哪里?n库:收集经常使用的函数到一起_printf_scanf._
11、printf:._scanf:.Dictionary?库文件一定叫.lib?48C/C+的实现n函数的地址和函数指针n生成程序的全过程.c.cpp.pas.f.asm.obj编译器汇编器.h.hpp.inc.tlib.exe.libtlink.exe.exe头文件路径库文件路径源文件路径输出路径中间临时输出路径49C/C+的实现n函数的地址和函数指针n函数地址n函数的执行入口在内存中的地址n理论上:执行文件被加载到内存后才能确定函数地址n实际上:系统均有很强的约定,大多数函数地址可以在连接时确定n函数指针n指向函数的入口的指针n有什么用?50C/C+的实现n函数指针n作用:调用所指向的函数n修
12、改函数的代码?n获得函数的代码?n一般情况下不作这些用处n理论上可行n为什么用指针?n不用名?51C/C+的实现n函数指针n当编译的时候无法确定函数名,则不能用名调用函数,只能用指针n例1:排序算法,编译时不能确定需要排序的数组的具体类型,就无法确定比较函数n例2:虚函数,编译时无法确定指向基类的指针的实际类型,就无法确定该用哪个函数n虚函数在编译器中是用函数指针实现的52C/C+的实现n函数指针n定义和使用函数指针类型的语法typedef int(*TCmp)(const void*,const void*);基本上是函数的声明可以不加名字差异所在void qsort(void*base,size_t nelem,size_t width,TCmp cmp)int cmpResult=cmp(void*)(int)base)+width*);函数指针可以如一般函数名一样使用函数指针类型可以如一般变量类型使用53
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。