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。而指针则标记某个物理内存地址,两者是不同的概念。