一套面试题总结代码
面试例题1:
如何用一个宏定义find求一个结构体ctype里某个变量cnum相对了ctype的编移量 ?
如:
view sourceprint?stuct student
{
int a;
char b[20];
double ccc;
}
则:
find(student,a); //等于0
find(student,b); //等于4
answer:
#define find(struc, e) (size_t)&(((struc*)0)->e)
(struc*)0 //表示将常量0强制转化为struc *型指针所指向的地址
&(((struc*)0)->e) /*表示取结构体指针(struc*)0的成员e的地址,因为该结构体的首地址为0,
所以其实就是得到了成员e距离结构体首地址的偏移量.*/
(size_t) //是一种数据类型,为了便于不同系统之间移植而定义的一种无符号型数据,
一般为unsigned int*/
(struc*)0 // 表示假设在0地址处有一个结构体struc
((struc*)0)->e // 表示在0地址处的结构体struc的成员e
&(((struc*)0)->e) // 表示在0地址处的结构体struc的成员e 的地址
(size_t)&(((struc*)0)->e) //将0地址处的结构体struc的成员e 的地址转换成整数类型
二:const
1: what does the keyword "const" means in c program ? please at least make
two examples about the usage of const.
parse:在c程序中,const的用法主要有定义常量、修饰函数参数、修饰函数返回值等3个用处。
在c++程序中,它还可以修饰函数的定义体,定义类中某个成员函数为恒态函数,即不改
变类中的数据成员。
answer:
(1)可以定义const常量。
(2)const可以修饰函数的参数和返回值,甚至函数的定义体。被const修饰的东西都受到强
制保护,可以预防意外的变动,能提高程序的健壮性。
2:const 与 #define相比有什么不同 ?
c++语言可以用const定义常量,也可以用#define定义常量,但是前者比后者有更多的优点.
answer:
(1)const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行安全检查,而对后者
只进行字符替换,没有类型安全检查,并且在字符替换中可能会产生意料不到的错误(边际效应).
(2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试.在c++程序
中只使用const常量而不使用宏常量,即const常量完全取代宏常量.
相关知识,点击链接: c++中的常量
3:在下述情况下,如果要修改类的成员变量,应该怎么办
class a_class
{
void f() const
{
}
}
answer:
在const成员函数中,用mutable修饰成员变量名后,就可以修改类的成员变量了。
sample
#include
class c {
private:
mutable int m_count;
public:
c(int i):m_count(i) {}
int add() const {
return ++m_count;
}
int minus() const {
return --m_count;
}
int print() {
printf("m_count = %dn", m_count);
}
};
int main() {
c tmp(5);
printf("before add: ");
tmp.print();
tmp.add();
printf("after add : ");
tmp.print();
puts("");
printf("before minus: ");
tmp.print();
tmp.minus();
printf("after minus : ");
tmp.print();
return 0;
}
sizeof
#include
struct node1 {
char a3;
int a1;
short a2;
};
struct node2 {
int a1;
char a3;
short a2;
};
int main() {
printf("%dn", sizeof(node1));
printf("%dn", sizeof(node2));
return 0;
}
answer:
结构体对齐:以结构体里最长的数据单元为对齐单元。
所以结构体的长度是最长的数据元素的整数倍
sizeof(node1);
|char|---|---|---|
|-------int------|
|--short-|-------|
sizeof(node2);
|-------int------|
|char|---|-short-|
下面程序输出什么?
#include
int main() {
int a = 4;
printf("%dn", sizeof(a = 6));
printf("%dn", a);
return 0;
}
answer:
sizeof不是函数,也不是一元运算符,它是类似宏定义的特殊关键字,sizeof()括号内
的内容在编译过程中是不被编译的,而是被替代类型,如int = 8; sizeof(a)。在编译
过程中不管a是什么值,只是被替代成类型sizeof(int),结过为4。如果是sizeof(a = 6)
呢?也一样是转换成sizeof(int),但需要注意的是:a = 6是不被编译的,所以执行完后,
a的值不变。
4 4
4:下面代码的输出结果是什么?
#include
char var[10];
int test(char var[]) {
return sizeof(var);
}
int main() {
printf("%dn", test("hello world"));
return 0;
}
answer:
c/c++传递数组永远是传递数组的首地址,是一个指针。
即int test(char va[]);等价于int test(char var *);等价于int test(char var[8]);
只要是指针类型,sizeof的大小就是4。
4
5:一个空类的空间占多少? 多重继承的空类呢?
answer:一个空类所占的空间为1,多重继承的空类所占的空间仍然为1。
sample:
#include
using namespace std;
class a {};
class a1 {};
class b : public a {};
class c : public virtual b {};
class d : public a, public a1 {};
int main() {
cout << sizeof(a) << endl;
cout << sizeof(b) << endl;
cout << sizeof(c) << endl;//虚继承设计到虚表(虚指针),所以sizeof(c)的大小为4
cout << sizeof(d) << endl;
return 0;
}
内联函数与宏定义的差别
内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用,在编译的时候内联函数可以直接呗镶嵌到目标代码中。
内联函数要做参数类型检查,这是内联函数跟宏相比的优势。
inline是指嵌入代码,就是在调用函数的地方不是跳转,而是把代码直接写到那里去。对于短小的代码来说,inline可以带来一定的效率提升,
而且和c时代的宏函数相比,inline更安全可靠。可是这个是以增加空间消耗为代价的。至于是否需要inline函数就需要根据你的实际情况取舍了。
inline一般只用于如下情况:
(1)一个函数不断被重复调用。
(2)函数只有简单的几行,且函数不包含for、while、switch语句。
●一般来说,我们写小程序没有必要定义成inline,但是如果要完成一个工程项目,当一个简单函数被调用多次时,则应该考虑用inline。
● 宏在c语言里极其重要,而在c++里用得就少多了。关于宏的第一规则是:绝不应该去使用它,除非你不得不这样做。几乎每个宏
都表明了程序设计语言里或者程序里或者程序员的一个缺陷,因为它将在编译器看到程序的正文之前重新摆布这些正文。宏也许
是许多程序设计工具的麻烦。所以,如果你使用了宏,你就应该准备着只能从各种工具(如排错系统、交叉引用系统、轮廓程序等)
中得到较少的服务。(--pass:宏还是很方便的,使用时要小心,并不是说宏一无是处,存在自然有其合理性)
宏是在代码处不加任何验证的简单替代,而内联函数是将代码直接插入调用处,而减少了普通函数调用时的资源消耗。
宏不是函数,只是在编译前(编译预处理阶段)将程序中有关字符串替换成宏体。
inline函数是函数,但在编译中不单独产生代码,而是将有关代码嵌入到调用处。
inline fact(float i) { return i * i; } // 没有写返回值的printf("bb= %d", fact(8)); // 调用时就是执行printf("bb= %d", 8*8);