嵌入式软件工程师笔试题_第1页
嵌入式软件工程师笔试题_第2页
嵌入式软件工程师笔试题_第3页
嵌入式软件工程师笔试题_第4页
嵌入式软件工程师笔试题_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

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

文档简介

char(*c)[5];int**p;for(inti=0;i<m_row;i++)//为每一行分配空间p[i]=newint[m_cols];voidgetmemory(int**&p,intm_row,int{p=newint*[m_row];//创建行指针for(inti=0;i<m_row;i++)//为每一行分配空间p[i]=new}voiddeletememory(int**&p,int{for(inti=0;i<m_row;i++)delete[]x[i];delete[]x;-|yingwang294于2006-10-31#include#include#include<malloc.h>char*getstring(void){charp[]=" oeveryone";returnp;}char{return(char}intmain(intargc,char*{char*p=getmemory();return0;}charp[]static...#include#include#include#include<assert.h>typedefstruct{intvalue;chartypedefstruct{head_thead;intpara;voidmain(void){message_t*message=NULL;head_t*head=NULL;message=(messaget*)malloc(sizeof(messaget));head=(head_t*)message;"(message);}#include<iostream>#include<string>usingnamespacestd;classStudent{Student()Student(conststring&nm,intsc=0:name(nm),score(sc)voidset_student(conststring&nm,intsc=0{name=nm;score=sc;}conststring&get_name(){return}intget_score(){return}stringname;intscore;//outputstudent'snameandvoidoutput_student(constStudent&student{cout<<student.get_name()<<"\t";cout<<student.get_score()<<endl;}int{Studentstu("Wang",85);output_student(stu);}Studentnamescore,有两个构造函数,有一个设置成员数据函数set_student,各有一个取得name和score的函数get_name()get_score()get_name()get_score()后面都加了const,而set_student()后面没有(const)。get_name()constconst的话,get_name()返回的是对私有数据成员name的,所以通过这个可以改变私有成员name的值,如Studentstu("Wang",85);stu.get_name()="Li";即把name由原来的"Wang"变成了"Li",而这不是我们希望的发生的。所以在get_name()前面加const避免这种情况的发生。那么,get_name()get_score()const的成员函数,如果没const修饰的话可不可以呢?回答是可以!但是这样做的代价是:const对象将不const成员函数了。如conststring&get_name();constintvoidoutput_student(constStudent&student{cout<<student.get_name()<<"\t";//如果get_name()cout<<student.get_score()<<}由于参数student表示的是一个对constStudent型对象的所以student不const成员函数如set_student()。如果get_name()和get_score()conststudent.get_name()和student.get_score()的使用就是的,这样就会给我们处理问题造成。const的对象之外,const对象也能够调用它。c/C++MakefileMakefile书写规则的人,也可以为自己的C/C++程序快速建立一个可工作的MakefileGNUMakeGCC编译器下正常工作。但是不能保证对于其它版本的Make和编译器也能正常工作。whyglinuxAThotmailDOTcom邮箱和作者联系。Makefile 尽量将自己的源程序集中在一个中,并且把Makefile和源程序放在一起,这样用起来比较方便。当然,也可以将源程序分类存放在不同的中。在程序中创建一个名为MakefileMakefile的内容复制到这个文件中(注意:在的过程中,Makfile中各命令前面的Tab字符有可能被转换成若干个空格。这种情况下需要把Makefile命令前面的这些空格替换为一个将当前工作Makefile所在的Makefile只支持在当前目录中的调用,不支持当前和Makefile所在的路径不是同一的情况。程序编译和连接成功后产生的可执行文件在Makefile中的PROGRAM变量程序所在的路径在SRCDIRS中设定。如果源程序分布在不同的 在SRCDIRS中一一指定,并且路径名之间用空格分隔。Makefile目标Makefileomakeallomake.o目标文件,不进行连接(一般很少单独使用)omakeomakecleomakemakeclean&&makeall。下面提供两个例子来具体说明上面Makefile的用法。 oWorld程这个程序的功能是输出o,world!这样一行文字。由o.h、o.c、main.cxxCC++个C和C++混编程序。/*Filename:*Cheader #ifdef extern"C"{voidprint_o();#ifdef }/*Filename:*Csource#include"o.h"#include<stdio.h>voidprint_{puts("o,world!"}/*Filename:*C++source#include"int{return} 中,也把Makefile文件拷贝到目录中。之后,对Makefile的相关项目进行如下设置: := #设置运行程序 := #源程序位于当 :=.c.cxx #源程序文件有.c和.cxx两种类型 :=-g #为C目标程序包含GDB可用的调试信息CXXFLAGS:=-g #为C++目标程序包含GDB可用的调试由于这个简单的程序只使用了C标准库的函数(puts),所以对于CFLAGSCXXFLAGS没有过多的要求,LDFLAGSCPPFLAGS经过上面的设置之后,执行make命令就可以编译程序了。如果没有错误出现的话,./o就可以运行程序了。加新的源文件,只要它们的扩展名是已经在Makefile中设置过的,那么就没有必要修改Makefile。本文的写作目的并不在于提供C/C++strcpystrcpy很可能只1:voidvoid{charstring[10];char*str1="strcpy(string,str1);}voidvoid{charstring[10],str1[10];inti;for(i=0;i<10;{str1[i]=}strcpy(string,str1}voidtest3(char*{charif(strlen(str1)<=10 strcpy(string,str1}试者strcpy(string,str1)调用使得从str1内存起到string内存起所的字节数具有不确定性可以给7分在此基础上库函数strcpy工作方式的给10分;3,if(strlen(str1)<=10)if(strlen(str1)<10)strlenstrcpystrcpy10,voidvoidstrcpy(char*strDest,char*strSrc{while((*strDest++=*strSrc++)!=‘\0’}voidvoidstrcpy(char*strDest,constchar*strSrc{while((*strDest++=*strSrc++)!=‘\0’}voidvoidstrcpy(char*strDest,constchar{assert((strDest!=NULL)&&(strSrc!=NULL));while((*strDest++=*strSrc++)!=‘\0’);}char*strcpy(char*strDest,constchar*strSrc{assert((strDest!=NULL)&&(strSrc!=NULL));char*address=strDest;while((*strDest++=*strSrc++)!=‘\0’return}多,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!strcpy10strlen函数了,完美的版本为:intstrlen(constchar*str)//const}}assert(strtNULL0intlen;while((*str++)!='\0'{}return{voidvoidGetMemory(char*p{p=(char*)malloc(100}voidTest(void{char*str=NULL;GetMemory(strstrcpy(str," oworld");printf(str);}charchar*GetMemory(void{charp[]=" oworld";returnp;}voidTest(void{char*str=NULL;str=GetMemory();printf(str);}voidvoidGetMemory(char**p,intnum{*p=(char*)malloc(num}voidvoidTest(void{char*str=NULL;GetMemory(&str,100);strcpy(str," o");printf(str);}voidvoidTest(void{char*str=(char*)malloc(100);strcpy(str," o");(str}4GetMemory(char*p函数的形参为字符串指针,在函数内部修charchar*str=NULL;GetMemory(str 5中charcharp[]="returnp;o6GetMemory4GetMemory的参数为字符串指针的指针GetMemory中执行申请内存及赋值语句*p*p=(char*)malloc(numif(*p==NULL{}charchar*str=(char*) (str)后未置str为空,导致可strstr=50~60的错误。但是要完全解答正确,却也绝非易事。swap(swap(int*p1,int*p2{int*pp是一个“野”*p=*p1=*p2=}在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的 在VC++中DEBUG运行时提示错误“AccessViolation”。该程序应该改为:swap(swap(int*p1,int*p2{intp=*p1=*p2=}1BOOL,int,float“零值”if语句(假设var) int constfloatEPSINON=ifif((x>=-EPSINON)&&(x<=intif(!var)if(!var),上述写法虽然表明其为“逻辑”if判断一个数值型变量(short、int、long等),应该用if(var==0)不可将float变量用“==”或“!=”法转化成“>=”或“<=”if(x==0.0)0分。voidFunc(charstr[100]{sizeof(str)=}void*p=malloc(100);sizeof(p)=? sizeof(sizeof(str)=4sizeof(p)=4 Func(charstr[100])函数中数组名作为函数形参时,在函数体内,数组名失charcout<<sizeof(str)<<charstr++;str不是左值//注意与上面的数组作函数形参WindowsNT32位平台下,指针的长度(占用内存的大小)4字节,故sizeof(str)、sizeofp)4leastleast=MIN(*p++,#define#defineMIN(A,B)((A)<=(B)?(A):MIN(*p++b)会产生宏的副作用#define#defineMIN(A,B)(A)<=(B)?(A):(B)#defineMIN(A,B)(A<=B?A:B)宏定义#defineMIN(A,B)((A(B(AB))MIN(*p+b)的作用((*p++)<=(b)?(*p++):#ifndef#ifndefINCvxWorksh#defineINCvxWorksh#ifdefcplusplusextern"C"{#ifdef }#endif/* INCvxWorksh#ifndef#ifndefINCvxWorksh#defineINCvxWorksh的作用是防止被重复C++symbolC语言的不同。例如,假设某个函数的原型voidvoidfoo(intx,int将该函数编译为_fooCC++的函数了。voidLoopMove(char*pStr,intsteps{}voidvoidLoopMove(char*pStr,intsteps{intn=strlen(pStr)-chartmp[MAX_LEN];//这是何物啊??重新定义一个中间数组strcpy(tmp,pStr+n);把前n位 给tmpstrcpy(tmp+steps,pStr);把pstr 给tmp,从steps位开*(tmpstrlenpStr\0';截取strlen()strcpy(pStr,tmp}voidLoopMove(char*pStr,intsteps{intn=strlen(pStr)-steps;chartmp[MAX_LEN];memcpy(tmppStrn,steps);将后steps位memcpy(pStr+steps,pStr,n);memcpy(pStr,tmp,steps);}织WAVWAV格式的各项信息。4444422242244typedeftypedefstruct{charcRiffFlag[4];UIN32nFileLen;charcWaveFlag[4];charcFmtFlag[4];charcTransition[4];UIN16nFormatTag;UIN16nChannels;UIN16charcTransition[4];UIN16nFormatTag;UIN16nChannels;UIN16nSamplesPerSec;UIN32nAvgBytesperSec;UIN16nBlockAlign;UIN16nBitNumPerSample;charcDataFlag[4];UIN16}WAVbuffer开始的内存单元内,则分析文件格WAVEFORMATWAVEFORMATmemcpy(&waveFormat,buffer,sizeof(WAVEFORMAT)6考查面试者组织数据结构的能力,有经验的程序设计者将属于一个整体的class String(constchar*strNULL);// String(constString&other);// ~String(void);// String&operateconstString&other);// char*m_data;// String::String(constchar*str){{ m_datanewchar[1];//得分点:对空字符串自动申请存放结束 //m_dataNULL *m_data= intlength= m_datanewchar[length+1];//NULL strcpy(m_data,}//String的析构函数{deletem_data;//delete}String::String(constString&other) //得分点:输入参数为const型intlength=m_data=newchar[length+1]; NULL判断}String&String::operate=(constString&other)//得分点:输入参const型if(this returndelete intlength=strlen(other.m_datam_datanewchar[length+1];m_dataNULL判strcpy(m_data,other.m_datareturn }C++60%以上!在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求, (2constconst; constconstclassAoperator*(constclassA&a1,constclassA&operator*的返回结果必须是一个const对象。如果不是,这样的代码也不classAclassAa,b,(a*bc;//对a*b操作(a*bc试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是 int{ union int char } c.a=1;0X00000001节,c.b为一个字 return(c.b1);c.b00c.b}嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用16bitendianCPU内存中的存放方式(0x4000开始存放)为:32bit宽的数0x 设从地址0x4000开始存放)为:union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该21+2+3+…+n的值(假定结果不会超过长整型变量的intintSum(intn{return((long)1+n)*n/}//或return(1ln)*n*n2intintSum(intn{}}longsum=for(inti=1;i<=n;i++{sum+=}returnshortflag;void{}这段程序等待内存变量flag的值变为1(怀疑此处是0,有点疑问,)之后才运行do2()。flag的值由别的程序更改,这个程序可能是某个硬件中断服务程序。例如:如果DSPflag1,这样上面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的值先读入某个寄存器,然后等待那个寄存的内容不可能被中断服务程序修改。为了让程序每次都真正flag变量的值,就需volatileshortvolatile也可能能正常运行,但是可能修改了编译器的优化级别volatile关键字。C语言void及void指针探void的字面意思是“无类型”,void*则为“无类型指针”,void*可以指向任何类void几乎只有“注释”void变量,void这行语句编译时会出错,提示“illegaluseoftype'void'”voidp1和p2指向不同的数据类型,则必须使用强制类型转换运算符把赋值float*p1;int*p2;p1=p2;p1=p2语句会编译出错,提示“'=':cannotconvertfrom'int*'to'float*'”,必须改为:p1=(floatvoid*p1;int*p2;p1=但这并不意味着,void*也可以无需强制类型转换地赋给其它类型的指针。因为void*p1;int*p2;p2=提示cannotconvertfrom'void*'to'int*'”void类型。例如:add(inta,intb{returna+}intmain(intargc,char*{printf("2+3=%d",add(2,3)}2+3=博士《高质量C/C++编程》中提到:“C++语言有很严格的类型安全检查,VisualC++6.0add函数的编译无错也无警告且运行正确,所以不能寄希在C++语言中一个这样的函数:int{return}TurboC2.0中编译:#include"stdio.h"{return}{}1C语言中,可以给无参数的函数传送任意类型的C++C++中,不能向无参数的函数传送任何参数,出错提示“'fun':functiondoesnottake1parameters”。规则三使用void指针类型ANSI(AmericanNationalStandardsInstitute)void指针void*pvoid++;//ANSI:错误pvoid1;/ANSI:错误int*pint;char*一致。pvoid++;//GNU:正确pvoid1;GNU:正确void*(char*)pvoid++;//ANSI:正确;GNU:正确(char*)pvoid1;/ANSI:错误;GNU:正确ANSI标准。void*memcpy(void*dest,constvoid*src,size_tlen);void*memset(void*buffer,intc,size_tnum);这样,任何类型的指针都可以传入memcpy和memset中,这也体现了memcpymemsetvoid*char*,那才叫真的奇怪memcpy和memset明显不是一个“纯粹的,脱离低级趣味的”函数!intmemsetintarray,0,100*sizeof(int)intarrayintintarray1[100],memcpy(intarray1,intarray2,100*sizeof(int));//将intarray2拷贝给有趣的是,memcpy和memsetvoid*类型,标准库函数的编voida;//错误function(voida错误void体现了一种抽象,上的变量都是“有类型”的,譬如一个人不是void数据类型。正如不能给抽象基类定义一个实例,我们也不void(void为“抽象数据类型”)变量。关于CONSTvoidconstint}consta是一个int类型的局部自动变量,0。constinta;intconst是等价的。于是此处要清晰的明白,const修饰的对象是谁,是a,和int没有关系。const要求他所修饰的对象为常量,constinta;intconstconstinta;constdoubleconstint*const修饰符号。int*p;int其实我们想要说的是,*p是int类型。那么显然,pintint*p;intconstint*constint(*p);intconstp+=8*p=3; int*constp;p是一个指向int形式变量的指针。p+=8;//*p=3;constint*constp+=8;*p=3;const还有一个作用就是用于修饰常量静态字符串。constchar*导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就const的好处。让逻辑错误在编译const还可以用来修饰数组constchars[]="David";memmove--copybyteStandardCLibrary(libc,-lc)#include<string.h>void*memmove(void*dst,constvoid*src,size_t它的第二个参数,是要将什么样的字符串出去,我们对这段内存区域只做读于是,我们站在这个函数自己的角度来看,src这个指针,它所指向的内存内所存const修饰。constchar*s=" charbuf[100];memmove(buf,s,6);strcpy或memcpy更好const即可),那么这个程序在运行的时候一定会。这里还要说明的一点是在函数参数中const一般用来指针而不是变量本身。size_tlen,len的值,那么是否应该把len也为常量呢?可以,可以这么做。我们来分析这么做有什么优劣。const,那么对于这个函数的实现者,可以防止他在实现这个函数的时候修copy。所以,const一般只用来修饰指针。intexecv(constchar*path,char*constconst,我们可以看出char*char*类型的指argv[1]=NULLargv[0][0]='a';合法const。如果它要在多个文件间共享,那么就牵扯到一个类型的问题。/*file1.hexternconstdouble/*file1.cconstdouble#include /*constant.h*/staticconstpi=3.14;该变量实际上还是被定义了多次,占用了多个空间,不过在加了static关键字 const的作用。const的好处,是引入了常量的概念,让我们不要去修改不该修改的内存。直接的作用就是让的逻辑错误在编译期被发现。所以我们要尽可能的多使用const。但是很多人并不习惯使用它,更有甚者,是在整个程序编写/调试完后才补const。如果是给函数的补const,尚好。如果是给全局/局部变量补const,那 联合也是一种新的数据类型,它是一种特殊形式的变量。union联合名}联合变量名联合表示几个变量公用一个内存位置,uniona_bc{intcharlgc的联合变量,可写成:uniona_bclgc;,当一个联合被说明时,编译程序自动地产生一个变量,其长度为联合中最大的变量为指针时,也要用"->;"符号,此时联合成员可表示成:另外,联合既可以出现在结构内,它的成员也可以是结构。intage;char*addr;inti;char*ch;若要结构变量y[1]中联合x的成员i,可以写成:结构和联合都是由多个不同的数据类型成员组成,但在任何同一时刻,联合转只存放了一个被选中的成员,而结构的所有成员都存在。对于联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而4:{ inti; charfirst;char printf("%c%c\n",number.half.first,mumber.half.second); printf("%x\n",number.i);}}从上例结果可以看出:i赋值后,firstsecond的值;当给firstsecond赋字符后,ASCIIi的低八位和高八位。Volatile关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,以件(B线程改变变量的值。A线程进入死循环。volatile一个由c/C++2、堆区(heap)—和未初始化的静态变量在相邻的另一块区域。-程序结束后有系统释放inta=0;全局初始化区char*p1;全局未初始化区{intb;chars[]"abc";char*p2;char*p3"123456123456\0在常量区,p3在栈上。staticintc=0;全局(静态)初始化区p1=(char*)malloc(10);p2=(charstrcpy(p1,"123456");123456\0intb;系统自动在b开辟空间c中malloc函数p1=(char*)malloc(10);p2(charnew分配的内存,一般速度比较慢,而且容易产生内存碎片,不过堆和栈中的chars1[]="aaaaaaaaaaaaaaa";char*s2"bbbbbbbbbbbbbbbbb";aaaaaaaaaaa是在运行时刻赋值的;#includevoid{chara=charc[]= char*p a=a=}10:a=8A4DF1movcl,byteptr[ebp-0Fh]A884DFCmovbyteptr[ebp-4],cl11:a=D8B55ECmovedx,dwordptr[ebp-14h]8A4201moval,byteptr[edx+1]8845FCmovbyteptr[ebp- 先把指针值读到edx中,在根据edx 使用栈就象我们去饭馆里吃饭,点菜(发出申请)、付钱、和吃(使 那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论下文中的C语言代码如没有特别 默认都使用VC编译的release版。首先,来了解一下C语言的变量是如何在内存分部的。C语言有全局变(Global)、本地变量(Local,静态变量(Static)、寄存器变量#include<stdio.h>intg1=0,g2=0,g3=0;intmain(){staticints1=0,s2=0,s3=0;intv1=0,v2=0,v3=0;printf("0x%08x\n",&v1);打印各本地变量的内存地址printf("0x%08x\n",&g1);打印各全局变量的内存地址printf("0x%08x\n",&s1);打印各静态变量的内存地址return}据区一般就是“堆栈”。“(stack)”和“堆(heap)”是两种不同的动态数据堆栈可以通过“址”和“栈顶”地址来描述。全局变量和静态变量分配在地址和偏移量来本地变量。 │……│……│……堆栈是一个先进后出的数据结构,栈顶地址总是小于等于栈的址。我和堆栈的平衡。windowsAPIANSIC的函数调用规则是“stdcall”和“cdecl”前缀区分。先看下面这段代码:#includevoid stdcallfunc(intparam1,intparam2,int{intvar1=param1;intvar2=param2;intprintf("0x%08x\n",?m1打印出各个变量的内存地址}int{return0;} │……│var1│var2│var3│RET │parameter1│parameter2│parameter3 │…… 址EBP)、高端内存区4个字节);接着就初始化本地变量的内存空间。由于“stdcall”调 func 83EC0Csub 8B442410moveax,dwordptr 8B4C2414movecx,dwordptr B8B542418movedx,dwordptr movdwordptr[esp], 8D442410leaeax,dwordptr 894C2404movdwordptr[esp+04], 83C43Caddesp, C恢复堆栈,回收本地变量 C3ret000C :6A03:6A02:6A01:E875FFFFFF #include#includevoid stdcall{charlpBuff[8]="\0";}int{return0;}编译后执行一下回怎么样?哈,“"0x "内存。该内存不能为"read"。”,“操作”喽!"41"就是"A"的16进制的ASCII码了,那明显就是strcat这句出的问题了。是一个覆盖RET的数据,紧接着是一段scode,那只要着个RET地址能指向这段scode的第一个指令那函数返回时就能执行scode了。但是软件的不同版本和不同的运行环境都可能影响这段scode在内存中的位置,那么要构造这个RET是十分的。一般都在RET和scode之间填充大量的NOP指令,使得exploit有更强的通用性。 │……│buffer│<—││RET│<—指向 │NOP……│<—NOPRET│NOP││ code││……的朋友都知道,C++new关键字来动态分配内存。来看下面的#include#include#includevoid{char*buffer=newchar[128];charbufflocal[128];staticcharbuffstatic[128];printf("0x%08x\n",buffer);//打印堆中变量的内存地址printf("0x%08x\n",bufflocal)打印本地变量的内存地址//}void{}new关键字分配的内存即不在栈中,也不在静态数据区。VCwindows下的“堆(heap)”new关键字的内存动态分配。在讲“堆”之前,先来了解一下和“堆”API函数:HeapAlloc在堆中申请内存空间HeapCreate创建一个新的堆对象HeapDestroy销毁一个堆对象 HeapWalk枚举堆对象的所有内存块GetProcessHeap取得进程的默认堆对象GetProcessHeaps取得进程所有的堆对象HANDLEhHeap=GetProcessHeap();char*buff=HeapAlloc(hHeap,0,8); //#include_CRTIMPint cdecl*printf)(constchar*,...);//STL写到这里,我们顺便来复(*注)printf函数是C语言的标准函数库中函数,VC的标准函数库由由函数定义可见,printf的参数个数是可变的,函数内部无法预先知道调衡堆栈,这里便使用了cdecl调用规则。BTW,Windows 它使用cdeclprintf函数一样,这是由于它的参数个数是void{HANDLEhHeap=GetProcessHeap();char*buff=HeapAlloc(hHeap,0,0x10);char*buff2=HeapAlloc(hHeap,0,0x10);HMODULEhMsvcrt=LoadLibrary("msvcrt.dll");printf=(void*)GetProcAddress(hMsvcrt,"printf");}hHeapbuffhHeap这个句柄就处存放了指向进程所有堆的地址列表的指针。windowsAPI都使windows2000ANSI版ANSIUnicode字符串的。对一个堆的是顺序进行的,同一时刻只能有一个线程WORD数据的内存起始地址能被2除尽,x86CPU能直接对齐的数VCDev-C++lcc三个不同编译器编译出来的程序的执行结果:#include<stdio.h>intmain(){inta;charb;intc;return0;}变量在内存中的顺序:c(4字节)-3字节-b(1字节)-a(4字char4字节,浪费内存哦。作。CPUESP寄存器存放当前线程的栈顶指针,EBP寄存器中保存当地址,当CPU执行完当前的指令后,从EIP寄存器中下一条指令的用到的关键字如下:new、malloc、delete、等等。,栈:由系统自动分配。例如在函数中一个局部变量intb;系统b开辟空间。,Windows下,栈是向低地址扩展的数据结构,是一块连续的内overflow。因此,能从栈获不过用起来最方便WINDOWSVirtualAlloc语句的下一条可执行语句)的地址然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意:静态堆:char*s1="owWord";是在编译时就确定的栈:chars1[]="owWord";是在运行时赋值的;用数组比用*{}usingnamespacestd;intmain(){inta[2]={-stringstr="*******************";inti=0,j=9,t=1;{}return}intmain(){char*tempStr="*******************";char*blank="";inti=char*dataStr[20];charblankstr[10];for(i=0;i<19;{memset(dataStr,0,20);if(i<10){memcpy(dataStr,tempStr,(i+1)*2-1);}{memcpy(dataStr,tempStr,(19-i)*2-1);}printf("%s\n",dataStr);}return}#include<stdio.h>#include<string.h>#include<stdlib.h>#defineMAXSIZE19voidmain(){inti,k;charcharformat[30],stars[30],tmp[3];ch='*';for(i=0;i<MAXSIZE;{if(i<={k=(MAXSIZE+1)/2-{}}{k=i+2-(MAXSIZE+stars[MAXSIZE-1-(2*(i+1)-MAXSIZE-1)]=}}}intmain(intargv,int*{fo

温馨提示

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

评论

0/150

提交评论