程序员面试宝典--经典笔试题


1、赋值语句类型题

以下C++代码的输出是什么?

int i= 1;
void main()
{
int i = i;
cout<<i<<endl;
system("pause");
}

解析:虽然inti = i看起来很诡异,但是在C++语法上完全是合法的,其中int i的声明覆盖了main外中的int i的作用域,int i = i右边的i使用的是左边i的变量,也就是说使用左侧未初始化的i值对int i进行初始化,结果仍然是初始化状态。

延伸思考:这说明了函数中包括main中声明的变量都是没有进行初始化的,需要手动进行初始化。

2、类型转换

unsignedint a = 0xfffffff7;
unsigned char i = (unsigned char)a;
char *b = (char*)&a;
printf("%08x\n","%08x\n",i,*b);
system("pause");

解析:char占一个字节(8位),故而i为000000f7

char *b =(char*)&a;等价于

unsignedint *p = &a;

char *b =(char*)p; //此处的强制转换只是使得b指向a而已,但是*b的值还是a的值,即fffffff7

3、运算符问题

用一个表达式,判断一个数X是否是2的N次方(2,4,8......),不可使用循环语句

答案:!(x&(x-1))

4、const与#define相比有什么不同?

都可以定义常量,但是const相比后者有更多的优点。

a. const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且会在字符替换中可能会产生一些不可意料的错误(边际效应)

b. 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试,在C++程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。

5、引用和指针的不同(简答)

答:初始化,合法性检查,可修改性,应用范围

6、程序运行结果判定

voidGetMemory(char *p,int num)
{
p = (char *)malloc(sizeof(char) * num);
}

void main()
{
char *str = NULL;
GetMemory(str,100);
strcpy(str,"hello");
system("pause");
}

解析:毛病处在函数GetMemory中,void GetMemory(char *p,int num)中的*p实际上是主函数中str的一个副本,编译器总是要为函数的每个参数制作临时副本。在本例中,p申请了新的内存,只是把p所指向的内存地址改变了,但是str没有改变,因为函数GetMemory没有返回值,因此str并不指向p所申请的那段内存。事实上,没执行一次GetMemory就会申请一块内存,但申请的内存却不能有效释放,结果是内存一直被独占,最终造成内存泄露。所以该题的答案是程序崩溃,因为GetMemory并不能传递动态内存,Test函数中的str一直都是NULL

 

如果一定要用指针参数去申请内存,那么应该采用指向指针的指针,传str的地址给函数GetMemory,代码如下,

voidGetMemory(char **p,int num)
{
*p = (char *)malloc(sizeof(char) * num);
}

void main()
{
char *str = NULL;
GetMemory(&str,100);
strcpy(str,"hello");
system("pause");
}

但是我们一般使用函数返回值来传递动态内存,这种方式更为简单和方便理解,代码如下。

char*GetMemory(char *p,int num)
{
p = (char *)malloc(sizeof(char) * num);
return p;
}

void main()
{
char *str = NULL;
str=GetMemory(str,100);
strcpy(str,"hello");
system("pause");
}

进而推而广之,整形变量是如何传值的呢?代码如下:

voidGetMemory(int *p)
{
*p = 5;
}

void main()
{
int v;
GetMemory(&v);
cout<<v<<endl;
system("pause");
}

GetMemory把传进来的v参数的地址拷贝所指向的原值(还是原值)改变了,实现了目的。

需要注意的是v是没有初始化的,但是仍然是运行正确的,这点可能对于局部变量作用域是不可行的,但是对于参数貌似是可行的。

7、下面这个函数有什么问题?该如何修改?

 

8、C++中有了malloc/free,为什么还需要new/delete?

答:malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符,它们都可以申请动态内存和释放内存,但是它们之间是有区别的。

对于非内部数据类型的对象而言,只用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数,由于malloc/free是库函数而不是运算符,不在编译器的来控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

总之一句话:new/delete不是库函数,而是运算符。

9、句柄和指针的区别?

答:两者完全是不同的概念,windows系统用句柄标记系统资源,隐藏系统的信息。你只要知道有这个东西,然后去调用就行了,它是个32bit的uint。而指针则标记某个物理内存地址,两者是不同的概念。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值