C++程序员面试指南第4章

第4章 预处理、保留字
面试题1:简述#ifdef、#else、#endif、#ifndef的作用。
答案:这些条件编译指令主要有以下功能:
(1)利用#ifdef、#endif可将某程序功能模块包括进去,以向特定用户提供该功能。
(2)用于在子程序前加上标记,以便于追踪和调试。
(3)应对硬件的限制。
面试题2:宏和函数的区别?
答案:
(1)宏的引用只占编译时间,不占运行时间。
(2)宏的引用没有返回值。如果需要,需给整个表达式加上括号。
(3)宏的形参无类型。函数的形参必须要有类型。
(4)实参为表达式的情况。如果没有给表达式加上括号,可能会导致错误的结果,而函数不会。
(5)宏直接替代有可能导致副作用,函数不会。


面试题3: 用宏定义实现一个常数,用来表示一年有多少秒,忽略闰年的问题。要注意数据长度的问题(16位机)
答案: #define SECONDS_PER_YEAR (365*24*60*60)UL


面试题4:写一个“标准”宏MIN,这个宏输入两个参数并且返回较小的一个。
答案: #define MIN(a,b) ((a)<=(b)?(a):(b))


面试题5:typedef和define有什么区别?
答案:
(1)用法不同:typedef用来定义一种数据类型的别名,增强程序的可读性。define主要用来定义常量,以及
书写复杂度、使用频繁的宏。
(2)执行时间不同:typedef是编译过程的一部分,有类型检查的功能。define是宏定义,是预编译的部分,
其发生在编译之前,只是简单地进行字符串的替换,不进行类型的检查。
(3)作用域不同:typedef用作用域限定。define不受作用域约束,只要是在define声明后的引用都是正确的。
(4)对指针的操作不同:typedef和define定义的指针有很大区别。


面试题6:#define CHAR char* 和 typedef char* CHAR各有什么优劣?
答案: 由define定义的类型别名可以被其他修饰符扩展(如:unsigned),而typedef不可以。define定义的类型
别名代表指针时,其连续声明的变量中只有第一个是指针,其他的均为非指针的普通变量。而typedef能够保证连
续声明的所有变量均为同一类型。


# include<stdio.h>
# define CHAR char* //宏定义字符串CHAR替代字符串char*
unsigned CHAR i;      //用CHAR定义一个变量i


void main(void)
{
unsigned char a = 0;
i = &a;   //i指向a
printf("Before change: %d\n",*i);
*i = -5;  //i所指内容赋值-5
printf("After change: %d\n",*i);
return ;
}


运行结果:
Before change: 0
After change: 251


# include<stdio.h>
typedef  char* CHAR; //宏定义字符串CHAR替代字符串char*
unsigned CHAR i;      //用CHAR定义一个变量i


void main(void)
{
unsigned char a = 0;
i = &a;   //i指向a
printf("Before change: %d\n",*i);
*i = -5;  //i所指内容赋值-5
printf("After change: %d\n",*i);
return ;
}
编译错误:
 warning C4518: 'char ' : storage-class or type specifier(s) unexpected here; ignored
 error C2059: syntax error : ';'


# include<stdio.h>
# define  CHAR char*  //宏定义字符串CHAR替代字符串char*


void main(void)
{
char x = 1;
char y = 2;
char z = 3;
CHAR a,b,c;
a = &x;
b = y;
c = z;
printf("*a is: %d\n b is: %d\n c is: %d\n",*a,b,c);
return ;
}


运行结果:
*a is: 1
 b is: 2
 c is: 3


# include<stdio.h>
typedef  char* CHAR;   //宏定义字符串CHAR替代字符串char*


void main(void)
{
char x = 1;
char y = 2;
char z = 3;
CHAR a,b,c;
a = &x;
b = &y;
c = &z;
printf("*a is: %d\n*b is: %d\n*c is: %d\n",*a,*b,*c);
return ;
}


运行结果:
*a is: 1
*b is: 2
*c is: 3


面试题7:谈谈你对typedef的认识。
答案:typedef共有四种用途:
(1)定义一种类型的别名;
(2)用在旧的C代码中辅助声明struct.
(3)定义与平台无关的类型。
(4)为复杂的声明定义一个新的简单的别名。
还有两个注意事项:
(1)定义了一种类型的新别名后不能被其他的修饰符扩展。
(2)typedef是并不影响对象的存储特性的存储类关键字。


面试题8:关键字const是什么 const是非常常见的关键字,那么const是什么意思呢?它有什么作用呢?
答案:const是用来定义一个只读的变量或对象。主要优点:便于类型检查、同宏定义一样可以方便地进行
参数的修改和调整、节省空间,避免不必要的内存分配,为函数重载提供参考。


面试题9:请说明下面a的各种声明的含义。
const int a;
int const a;
const int *a;
int const *a;
int const *a const;
答案:
(1)const int a;和int const a;的意义是一样的,定义一个常整型数a。
(2)const int *a;定义了一个指向常整型数据的指针 a。
(3)int const *a;定义了一个指向整型数据的常指针a。
(4)int const*a const;定义了一个指向常整型数据的常指针a。


面试题10:常量有什么作用?const和define都可以用来定义常量,两者有什么区别?
答案:常量的引入可以增强程序的可读性,可以使程序的维护和调试更加方便,使书写简便。
const和define都可以定义常量。但是两者还是有区别的:
(1)const定义的常量有数据类型,而define没有。
(2)很多集成开发环境只支持对const定义的常量的调试,而不支持define定义的常量。
(3)const定义的常量是要分配内存空间的,而define定义的常量却不分配内存空间。
所以const定义的常量比define定义的常量有更多的优势,可以说const是对define的优化。


面试题11:static是比较常见的关键字,引入它有什么作用?
答案:static在C中主要用于定义全局静态变量、定义局部静态变量、定义静态函数。在C++中新增了
两种作用:定义静态数据成员、静态函数成员。


#include <stdio.h>
static int a;
void f1(void)
{
printf("In f1 a is:%d\n",a);
a = a + 1;
}


void main(void)
{
f1();
printf("In main a is:%d\n",a);
return;
}


运行结果:
In f1 a is:0
In main a is:1


#include <stdio.h>


void f1(void)
{
static int b;
printf("In f1 a is:%d\n",b);
b = b + 1;
}


void main(void)
{
f1();
printf("In main b is:%d\n",b);
return;
}
编译报错:
error C2065: 'b' : undeclared identifier


#include <iostream.h>
class A
{
public:
static int x;
int y;
A();
~A();
};
int A::x = 5;
A::A()
{
y = 6;
}
A::~A()
{


}


void main(void)
{
cout<<"In Main"<<endl;
cout<<"A::x:"<<A::x<<endl;
A a;
cout<<"a.x:"<<a.x<<endl;
cout<<"a.y:"<<a.y<<endl;
}
运行结果:
In Main
A::x:5
a.x:5
a.y:6


#include <iostream.h>
class A
{
public:
static int x;
static void set(int i);
static int get(void);
int y;
A();
~A();
};
int A::x = 5;
A::A()
{
y = 6;
}
A::~A()
{


}
void A::set(int i)
{
x = i;
}
int A::get( void )
{
return x;
}
void main(void)
{
cout<<"In Main"<<endl;
cout<<"A::get():"<<A::get()<<endl;
A::set(9);
cout<<"A::get():"<<A::get()<<endl;
A a;
cout<<"A::get():"<<A::get()<<endl;
a.set(8);
cout<<"A::get():"<<A::get()<<endl;
}


运行结果:
In Main
A::get():5
A::get():9
A::get():9
A::get():8


面试题12: extern是常见关键字,引入它有什么作用?
答案:extern标识的变量或函数声明定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻
找其定义。


#include"iostream.h"
int evalue;
void main()
{
evalue = 10;
cout<<evalue<<endl;
evalue++;
}
运行结果:
10


面试题13:请简述C/C++中变量的存储类型。
答案:变量的存储类型是对变量的作用域、存储空间、生存期的规定。变量的存储类型分为四种:自动类型(auto)、
寄存器类型(register)、外部类型(extern)、静态类型(static)。这四种类型说明的变量分别称为自动变量、寄存器
变量、外部变量与静态变量。


面试题14:volatile有什么作用
答案:volatile有如下作用:
*状态寄存器一类的并行设备硬件寄存器。
*一个中断服务子程序会访问到的非自动变量。
*多线程间被几个任务共享的变量。


面试题15:一个参数可以既是const又是volatile吗? 为什么?
答案:可以,用const和volatile同时修饰变量,表示这个变量在程序内部是只读的,不能改变的,只在程序外部条件
变化下改变,并且编译器不会优化这个变量。每次使用这个变量时,都要小心地去内存读取这个变量的值,而不是去
寄存器读取它的备份。


面试题16:一个指针可以使volatile 么?解释为什么?
答案:可以,因为指针和普通变量一样,有时也有变化程序的不可控性。常见的例子:子中断服务子程序修改一个指向
一个buffer的指针时,必须用volatile来修饰这个指针。











猜你喜欢

转载自blog.csdn.net/juluwangriyue/article/details/53862690