c语言笔试常见问题.doc
《c语言笔试常见问题.doc》由会员分享,可在线阅读,更多相关《c语言笔试常见问题.doc(20页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、1程序的内存分配1、栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap) 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。3、全局区(静态区)(static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 4、文字常量区常量字符串就是放在这里的。 程序结束后由系统释放5、程序代码区存放函数体的二进制代码。二、例子程序 这
2、是一个前辈写的,非常详细 /main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() int b; 栈 char s = abc; 栈 char *p2; 栈 char *p3 = ; 0在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来得10和20字节的区域就在堆区。 strcpy(p1, ); 0放在常量区,编译器可能会将它与p3所指向的优化成一个地方。 2、Const和static区别对于C/C+语言来讲,
3、const就是只读的意思,只在声明中使用;static一般有2个作用,规定作用域和存储方式.对于局部变量,static规定其为静态存储方式,每次调用的初始值为上一次调用的值,调用结束后存储空间不释放;对于全局变量,如果以文件划分作用域的话,此变量只在当前文件可见;对于static函数也是在当前模块内函数可见.static const 应该就是上面两者的合集.下面分别说明:全局:const,只读的全局变量,其值不可修改.static,规定此全局变量只在当前模块(文件)中可见.static const,既是只读的,又是只在当前模块中可见的.文件:文件指针可当作一个变量来看,与上面所说类似.函数:c
4、onst,返回只读变量的函数.static,规定此函数只在当前模块可见.类:const,一般不修饰类,(在VC6.0中试了一下,修饰类没啥作用)static,C+中似乎没有静态类这个说法,一般还是拿类当特殊的变量来看.C#中有静态类的详细说明,且用法与普通类大不相同. 3new delete 和malloc free的区别malloc与free是C+/C语言的标准库函数,new/delete是C+的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于m
5、alloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。 因此C+语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。4main() int x=10,y=10,i; for (i=0;x8;y=+i) printf(%d %d ,x-,y); 在循环语句for(表达式1;表达式2;表达式3)中,先执行表达式一,再执行表达式二,如果表达式二成立,就进入循环,第一次循环执行完后(本程序共两次循环),才执行表达式三(这是表达式三
6、第一次被执行),然后再执行表达式二,看其是否成立,如果成立,就进行第二次循环。如此循环,表达式一只在第一次循环时执行,以后不再执行,表达式三在第一次循环不执行,以后的每次循环都执行。如果你要这是为什么,我只能说这是规定,别的就不知道了。 5什么是静态成员变量 在C+类的成员变量被声明为static(称为静态成员变量),意味着它为该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见。 比如在某个类A中声明一个static int number;初始化为0。这个number就能被所有A的实例共用。在A的构造函数里加上number+,在A的析构函数里加上
7、number-。那么每生成一个A的实例,number就加一,每销毁一个A的实例,number就减一,这样,number就可以记录程序中共生成了多少个A的实例。 这只是静态成员的一种用法而已。6静态数据成员和静态成员函数在程序中是如何声明和定义的class Foopublic: static int a; stataic void func();静态数据成员和函数都是在声明前加static静态成员必须要在类外初始化,无法在构造函数内初始化。新标准的C+也允许在生命静态数据成员的是后直接加等于号进行初始化,但是大部分编译器不支持。所以最保险的办法就是在类定义的外面再写:int Foo:a = 0;
8、注意,这时候不需要再static了。函数则很普通成员函数的声明以及实现没区别,唯一要注意的是,静态函数是没有this指针的,因此不能访问任何非静态的其他成员函数或成员变量,如果要访问需要传递this指针进去,比如class Foopublic: int a; static void func(Foo* ptrFoo) a = 0; / 错误!a不是静态变量,无法访问! ptrFoo-a= 0; /正确。 void test() / 非静态成员函数调用静态成员函数可以传递this指针,让静态成员函数通过他来访问 / 其他成员函数和成员变量。 Foo:func(this); 7虚函数和纯虚函数区别
9、虚函数和纯虚函数在面向对象的C+语言中,虚函数(virtualfunction)是一个非常重要的概念。因为它充分体现了面向对象思想中的继承和多态性这两大特性,在C+语言里应用极广。比如在微软的MFC类库中,你会发现很多函数都有virtual关键字,也就是说,它们都是虚函数。难怪有人甚至称虚函数是C+语言的精髓。那么,什么是虚函数呢,我们先来看看微软的解释:虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本。摘自MSDN这个定义说得不是很明白。MSDN中还给出了一个例子,但是它的例子也并不能很好的说明问题。我们自己
10、编写这样一个例子:includestdio.hincludeconio.hclassParentpublic: chardata20; voidFunction1(); virtualvoidFunction2();/这里声明Function2是虚函数parent;voidParent:Function1() printf(Thisisparent,function1n);voidParent:Function2() printf(Thisisparent,function2n);classChild: publicParent voidFunction1(); voidFunction2()
11、;child;voidChild:Function1() printf(Thisischild,function1n);voidChild:Function2()printf(Thisischild,function2n);intmain(intargc,char*argv) Parent*p;/定义一个基类指针 if ( _getch()=c )/如果输入一个小写字母c p=&child;/指向继承类对象 else p=&parent;/否则指向基类对象 p-Function1();/这里在编译时会直接给出Parent:Function1()的入口地址。 p-Function2();/注意这
12、里,执行的是哪一个Function2? return0;用任意版本的VisualC+或BorlandC+编译并运行,输入一个小写字母c,得到下面的结果:Thisisparent,function1Thisischild,function2为什么会有第一行的结果呢?因为我们是用一个Parent类的指针调用函数Fuction1(),虽然实际上这个指针指向的是Child类的对象,但编译器无法知道这一事实(直到运行的时候,程序才可以根据用户的输入判断出指针指向的对象),它只能按照调用Parent类的函数来理解并编译,所以我们看到了第一行的结果。那么第二行的结果又是怎么回事呢?我们注意到,Functio
13、n2()函数在基类中被virtual关键字修饰,也就是说,它是一个虚函数。虚函数最关键的特点是“动态联编”,它可以在运行时判断指针指向的对象,并自动调用相应的函数。如果我们在运行上面的程序时任意输入一个非c的字符,结果如下:Thisisparent,function1Thisisparent,function2请注意看第二行,它的结果出现了变化。程序中仅仅调用了一个Function2()函数,却可以根据用户的输入自动决定到底调用基类中的Function2 还是继承类中的Function2,这就是虚函数的作用。我们知道,在MFC中,很多类都是需要你继承的,它们的成员函数很多都要重载,比如编写MF
14、C应用程序最常用的CView:OnDraw(CDC*)函数,就必须重载使用。把它定义为虚函数(实际上,在MFC中OnDraw不仅是虚函数,还是纯虚函数),可以保证时刻调用的是用户自己编写的OnDraw。虚函数的重要用途在这里可见一斑。再看下面的-上一篇:为何析构函数中的cout不起作用下一篇:菱形虚拟继承后,派生类的大小问题C+中虚函数和纯虚函数的概念,差别和分别存在的原因摘自:C+中虚函数和纯虚函数的概念,差别和分别存在的原因首先:强调一个概念定义一个函数为虚函数,不代表函数为不被实现的函数定义他为虚函数是为了允许用基类的指针来调用子类的这个函数定义一个函数为纯虚函数,才代表函数没有被实现定
15、义他是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。8请教C+深拷贝与浅拷贝区别并详细说一下如何应用浅拷贝就是对象的数据成员之间的简单赋值,如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:class Apublic:A(int _data) : data(_data)A()private:int data;int main()A a(5), b = a; / 仅仅是数据成员之间的赋值这一句b = a;就是浅拷贝,执行完这句后b.data = 5;如果对象中没有其他的资源(如:堆,文件,系统资源等)
16、,则深拷贝和浅拷贝没有什么区别,但当对象中有这些资源时,例子:class Apublic:A(int _size) : size(_size)data = new intsize; / 假如其中有一段动态分配的内存A();A()delete data; / 析构时释放资源private:int* data;int size;int main()A a(5), b = a; / 注意这一句这里的b = a会造成未定义行为,因为类A中的复制构造函数是编译器生成的,所以b = a执行的是一个浅拷贝过程。我说过浅拷贝是对象数据之间的简单赋值,比如:b.size = a.size;b.data = a.
17、data; / Oops!这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时,b先把其data指向的动态分配的内存释放了一次,而后a析构时又将这块已经被释放过的内存再释放一次。对同一块动态内存执行2次以上释放的结果是未定义的,所以这将导致内存泄露或程序崩溃。所以这里就需要深拷贝来解决这个问题,深拷贝指的就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。如:class Apublic:A(int _size) : size(_size)data = new
18、 intsize; / 假如其中有一段动态分配的内存A();A(const A& _A) : size(_A.size)data = new intsize; / 深拷贝A()delete data; / 析构时释放资源private:int* data;int size;int main()A a(5), b = a; / 这次就没问题了总结:深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝嵌入式篇1结构体位制,内存对齐 05 #include 06 07 typedef struct _A08 09 un
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 笔试 常见问题
限制150内