文档库 最新最全的文档下载
当前位置:文档库 › C语言面试问答题

C语言面试问答题

C语言面试问答题
C语言面试问答题

C语言面试问答题-标准化文件发布号:(9556-EUATWK-MWUB-WUNN-INNUL-DDQTY-KII

注意:该文档由本人从网络和面试经历中总结而得,不保证答案完全正确,如发现问题联系我:caijicheng2006@https://www.wendangku.net/doc/8e12779295.html,

1.头文件中的 ifndef/define/endif 干什么用?预处理

答:防止头文件被重复引用

2.#include 和#include “filename.h” 有什么区别?

答:对于#include 编译器从标准库开始搜索filename.h;对于#include “filename.h”编译器从用户工作路径开始搜索filename.h,没有搜索到再到标准库搜索filename.h

3.头文件的作用是什么?

答:(1).通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。

(2). 头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。

4.switch()中不允许的数据类型是?

答:实型

5.简述数组与指针的区别

答:数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。

6.分别给出BOOL,int,float,指针变量与“零值”比较的 if 语句(假设变量名为var)

答:

BOOL型变量:if(!var)

int型变量: if(var==0)

float型变量: const float EPSINON = 0.00001;

if ((x >= - EPSINON) && (x <= EPSINON)

指针变量:if(var==NULL)

剖析:

考查对0值判断的“内功”,BOOL型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思。

一般的,如果想让if判断一个变量的“真”、“假”,应直接使用if(var)、

if(!var),表明其为“逻辑”判断;如果用if判断一个数值型变量(short、int、long

等),应该用if(var==0),表明是与0进行“数值”上的比较;而判断指针则适宜用if(var==NULL),这是一种很好的编程习惯。

浮点型变量并不精确,所以不可将float变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。如果写成if (x == 0.0),则判为错,得0分。

7.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事?least = MIN(*p++, b);

答:

#define MIN(A,B) ((A) <= (B) (A) : (B))

MIN(*p++, b)会产生宏的副作用

剖析:

这个面试题主要考查面试者对宏定义的使用,宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。

程序员对宏定义的使用要非常小心,特别要注意两个问题:

(1)谨慎地将宏定义中的“参数”和整个宏用用括弧括起来。所以,严格地讲,下述解答:

#define MIN(A,B) (A) <= (B) (A) : (B)

#define MIN(A,B) (A <= B

A :

B )

都应判0分;

(2)防止宏的副作用。

宏定义#define MIN(A,B) ((A) <= (B)

(A) : (B))对MIN(*p++, b)的作用结果是:

((*p++) <= (b)

(*p++) : (*p++))

这个表达式会产生副作用,指针p会作三次++自增操作。

除此之外,另一个应该判0分的解答是:

#define MIN(A,B) ((A) <= (B) (A) : (B));

这个解答在宏定义的后面加“;”,显示编写者对宏的概念模糊不清,只能被无情地判0分并被面试官淘汰。

8.为什么标准头文件都有类似以下的结构

#ifndef __INCvxWorksh

#define __INCvxWorksh

#ifdef __cplusplus

extern "C" {

#endif

/*...*/

#ifdef __cplusplus

}

#endif

#endif /* __INCvxWorksh */

答:头文件中的编译宏

#ifndef__INCvxWorksh

#define__INCvxWorksh

#endif的作用是防止被重复引用。

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在symbol库中的名字与C语言的不同。例如,假设某个函数的原型为:

void foo(int x, int y);

该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是考这种机制来实现函数重载的。

为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C

语言的方式将该函数编译为_foo,这样C语言中就可以调用C++的函数了。9.请说出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显然不符合编程者的初衷,也没有任何意义。

剖析:

惊讶吗小小的static和const居然有这么多功能,我们能回答几个如果只能回答1~2个,那还真得闭关再好好修炼修炼。

这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。

10.const的用法,以及声明const变量与宏的区别;

答:const的用法有四种:

1. const常量,如const int max = 100;

2. const 修饰类的数据成员;

3. const修饰指针的情况;

4. 在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数。

区别:

1.const常量有数据类型,而宏常量没有数据类型;

2.编译器可以对前者进行类型安全检查,而对后者只能进行字符替换,没有类型安全检查,而且字符替换可能会带来料想不到的边界效应;

3. 有些集成化工具可以对const常量进行调试,但不能对宏量进行调试。11.C++中引用与指针的区别;

答:1 引用实际上是所引用的对象或变量的别名,而指针是包含所指向对象或变量的地址的变量。

2 引用在定义时必须初始化,而指针在定义时不初始化。

3 不可以有努NULL的引用,而可以有指向NULL的指针。

4 引用在初始化后不可以改变引用关系,而指针可以随时指向其他对象(非const指针)。

12.函数assert的用法?

答:断言assert是仅在debug版本起作用的宏,用于检查“不应该“发生的情况。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。

13.为什么数组名作为参数,会改变数组的内容,而其它类型如int却不会改变变量的值?

答:当数组名作为参数时,传递的实际上是地址。而其他类型如int作为参数时,由于函数参数值实质上是实参的一份拷贝,被调函数内部对形参的改变并不影响实参的值。

14.下列哪两个是等同的

int b;

A const int* a = &b;

B const* int a = &b;

C const int* const a = &b;

D int const* const a = &b;

各式表示的意思分别为:

答:

A const int* a = &b; //*a是const, 但指针a可变

B const* int a = &b; //a是const,但*a可变

C const int* const a = &b; //a和*a都是const,常量和指针的值都不能改变

D int const* const a = &b; //a和*a都是const,常量和指针的值都不能改变

因此C,D两者是相同的。

15.内存的分配方式的分配方式有几种?

答:一、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。

二、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

三、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

16.内联函数在编译时是否做参数类型检查

答:内联函数要做参数类型检查, 这是内联函数跟宏相比的优势

17.请问C++的类和C里面的struct有什么区别

答:class中默认的成员访问权限是private的,而struct中则是public的18.全局变量和局部变量有什么区别实怎么实现的操作系统和编译器是怎么知道的

答:生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;内存中分配在全局数据区

使用方式不同:通过声明后全局变量程序的各个部分都可以用到

局部变量只能在局部使用;分配在栈区

操作系统和编译器通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面。

19.论述含参数的宏与函数的优缺点。

答:宏是编译期的,函数是运行期的;宏不是实体,而函数是一个可寻址的实体;宏只是编译期替换,在程序里每遇到S(a,b),就用a*b代替,a和b两

相关文档