logo资料库

C语言类的面试题集(概念和易错).doc

第1页 / 共7页
第2页 / 共7页
第3页 / 共7页
第4页 / 共7页
第5页 / 共7页
第6页 / 共7页
第7页 / 共7页
资料共7页,全文预览结束
C 语言面试准备 这是我为面试 C 语言作的准备。 (1) 局部变量 全局变量 静态变量 const 常量 寄存器变量 宏定义的常量 static 变量 (注:包 括它们的内存分配,作用域,初始化等) 局部变量: 指在函数或者是在块语句中内部定义的变量,作用域为定义该变量的函数,内存分 配: 在栈中按地址从高到低分配。 全局变量: 通常在文件开头定义(理想位置),当这些函数以及同一个程序中的其他源程序文 件中的某些函数需要使用该全局变量时,在函数内部对该变量使用 extern 加以说明他是外部 的; 作用域: 在程序的执行过程中一直有效; 初始化: 定义时不做初始化则系统将自动为起 赋值数值型为 0 内存分配: 从静态储存区域分配。 静态变量: 用 static 语句可将变量声明为静态变量; 作用域是当前的子程序模块内, 而它的 生存期是到整个总程序的结束; 内存分配: 全局/静态存储区。 寄存器类型:使用关键字 register 声明寄存器类型的目的是将所声明的变量放入寄存器内,从 而加快程序的运行速度。 试题 8:请说出 static 和 const 关键字尽可能多的作用 解答: static 关键字至少有下列 n 个作用: (1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分 配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访 问; (3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限 制在声明它的模块内; (4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝; (5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访 问类的 static 成员变量。 const 关键字至少有下列 n 个作用: (1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对 它进行初始化,因为以后就没有机会再去改变它了; (2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二 者同时指定为 const; (3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改 变其值; 4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成 员变量; (5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左 值”。例如: const classA operator*(const classA& a1,const classA& a2); operator*的返回结果必须是一个 const 对象。如果不是,这样的变态代码也不会编译出 错: classA a, b, c; (a * b) = c; // 对 a*b 的结果赋值 操作(a * b) = c 显然不符合编程者的初衷,也没有任何意义。 (2) malloc/new, free/delete 之间的区别 malloc,free 是 C 语言的标准函数库,new/delete 是 C++的运算符,他们都可以动态申请内存和 释放内存; 对于非内部数据类型的对象而言, 光用 malloc/free 无法满足动态对象的需求. 对象要创建的 同时要自动执行构造函数,对象在消亡之前要执行析构函数,由于 malloc/free 不是运算符, 不 在编译器控制权限之内,不能把构造函数和析构函数的任务强加于 malloc/free 上. 因此,C++ 语言需要一个动态内存分配和初始化的运算符 new 和一个能完成清理与释放内存的运算符 delete 我们不要企图用 malloc/free 来完成动态对象的内存管理,应该用 new/delete。由于内部数据 类型的“对象”没有构造与析构的过程,对它们而言 malloc/free 和 new/delete 是等价的。 既然 new/delete 的功能完全覆盖了 malloc/free,为什么 C++不把 malloc/free 淘汰出局呢?这 是因为 C++程序经常要调用 C 函数,而 C 程序只能用 malloc/free 管理动态内存。 malloc/free 功能还有一好处,就是可以和 realloc 组合使用,在需要扩大内存块时不一定会导 致内存移动;而用 new/delete 实现时只能用 new[]-copy-delete[]操作序列完成,每次都会导 致内存移动。
(3) 内联函数宏定义区别, 各有什么优点. C++语言支持内联函数,目的就是为了提高函数的执行效率. 内联函数直接将代码插入调用外,从而减少了普通函数调用时的资源消耗, 要对参数类型进 行检查;而宏不是函数,只是在编译前(预编译处理之前)将程序中有关字符串替换成宏体,省去 了参数压栈、生成汇编语言的 CALL 调用、返回参数、执行 return 等过程, 不对参数类型进 行检查; 两者都能提高运行效率,但使用宏代码最大的缺点是容易出错,对于 C++ 而言,使用宏代码还 有另一种缺点:无法操作类的私有数据成员; C++ 语言的函数内联机制既具备宏代码的效 率,又增加了安全性,而且可以自由操作类的数据成员。所以在 C++ 程序中,应该用内联 函数取代所有宏代码,“断言 assert”恐怕是唯一的例外。 (4)内存分配有哪几种形式?分别为何?区别是什么?对编译速度影响是何? 内存分配有三种方式: 从静态存储区域分配, 内存在编译时就已分配好, 这块内存在程序整个运行期间都存在, 如: 全局变量,STATIC 变量. 在栈上分配, 如函数的局部变量可以在栈上分配,函数结束时自己被释放,栈内存分配的运算 内置于处理器的指令集中,效率高,内存分配是连续的,,栈是向低地址扩展的数据结构,但容量 有限; 从堆上分配,亦即动态内存分配, 程序运行时用 New/Malloc 分配, 程序员自己负责何时用 Delete/Free 释放, 若程序员不释放,程序结束时可能由操作系统回收.类似于链表,在内存 中的分布不是连续的,它们是不同区域的内存块通过指针链接起来的.一旦某一节点从链中 断开,我们要人为的把所断开的节点从内存中释放.动态内存的生存期由我们决定,使用灵 活(堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的 空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限 于计算机系统中有效的虚拟内存),但问题也多 申请效率的比较: 栈由系统自动分配,速度较快。但程序员是无法控制的。 堆是由 new 分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便. (5)struct 和 class 有什么区别?c 语言中的 struct 和 c++中的 struct 一样么?有什么区别? (一)默认继承权限。如果不明确指定,来自 class 的继承按照 private 继承处理,来自 struct 的继承按照 publ ic 继承处理; (二)成员的默认访问权限。class 的成员默认是 private 权限,struct 默认是 public 权限。
如果没有多态和虚拟继承,在 C++中,struct 和 class 的存取效率完全相同!简单的说就是, 存取 class 的 data member 和非 virtual function 效率和 struct 完全相同!不管该 data member 是定义在基类还是派生类的。 (6)说说什么是野指针?野指针什么情况下出现?(没有初始化,delete 后没有赋值为 NULL) 野指针不是 NULL 指针,是指向垃圾内存的指针,也就是指向不可用内存的指针,通常对这种 指针进行操作会 产生不可知道的错误,人们一般不会用错 NULL 指针,但是野指针很危险,IF 对它不起作用;于出现的情况有两种:没有初始化和 delete/free 没有赋值为 NULL. (7)你熟悉预编译指令么?条件编译是用来做什么的?你会写么? 预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。可见预处理 过程先于编译器对源代码进行处理. 下面是部分预处理指令: 指令 用途 # 空指令,无任何效果 #include 包含一个源代码文件 #define 定义宏 #undef 取消已定义的宏 #if 如果给定条件为真,则编译下面代码 #ifdef 如果宏已经定义,则编译下面代码 #ifndef 如果宏没有定义,则编译下面代码 #elif 如果前面的#if 给定条件不为真,当前条件为真,则编译下面代码 #endif 结束一个#if……#else 条件编译块 #error 停止编译并显示错误信息 条件编译指令将决定那些代码被编译,而哪些是不被编译的。可以根据表达式的值或者某个 特定的宏是否被定义来确定编译条件。 如: 为了避免那些只能包含一次的头文件被多次包含,可以在头文件中用编译时条件来进行控 制。例如: /*my.h*/ #ifndef MY_H #define MY_H …… #endif 1.#if 指令 #if 指令检测跟在制造另关键字后的常量表达式。如果表达式为真,则编译后面的代码,知 道出现#else、#elif 或#endif 为止;否则就不编译。 2.#endif 指令 #endif 用于终止#if 预处理指令。
#define DEBUG 0 main() { #if DEBUG printf(”Debugging\n”); #endif printf(”Running\n”); } 由于程序定义 DEBUG 宏代表 0,所以#if 条件为假,不编译后面的代码直到#endif,所以程 序直接输出 Running。 如果去掉#define 语句,效果是一样的。 (8)sizeof()这个函数你理解么?你能说出各种变量类型在 win 32 下的值么? sizeof 是运算符,可用于任何变量名、类型名或常量值,当用于变量名(不是数组名)或常 量时,它不需要用圆括号。它在编译时起作用,而不是运行时。 各个数据的值:int(4), char(1), double(8), short(2)。 (9)知道 sizeof(Type*)=4 吗?注:win32 下 指针变量用 4 个字节去存储,无论是什么类型,都是 4 个字节。 (10)题目求解 int array[5]= {}; sizeof(array)=? int Fuction(int a[]) { return sizeof(a); } Fuction(array)=? (11)函数不能返回栈指针 因为栈在函数退出的时候就会消除内存,所以不能返回栈指针。
分享到:
收藏