本文是对《程序员面试宝典》的学习总结,不足之处望多多批评指正。
每次看《程序员面试宝典》都有收获,但是不总结,有些东西无法真正掌握,这里对预处理、const和sizeof进行总结,希望能帮到更多人。大神亲喷。
预处理、const和sizeof问题是c++设计语言中的三大难点,也是各公司经常面试反复出现的问题。因此这里对其单独进行学习总结。
1、宏定义
宏定义主要考察的有:
(1)#define的基本语法知识(切记不能以分号结束,宏定义是没有符号结束的)
(2)实际使用中,最好把参数都用括号括起来,不然很容易出错。举个栗子:
#define chufa(a,b) a/b
那么multply(2+3,4+5)的结果是这样解释的:2+3/4+5;这实际上不是我们想要的,若写成
#define chufa(a,b) (a)/(b)
那么结果将是正确的。
2、const
(1)const修饰指针的情况
int b=100;
const int* a=&b;
int const* a=&b;
上面两种情况是等价的,只要const放在*的左边则代表const修饰是指针所指向的变量,如果const放在*的右边,则代表const修饰的是指针,即指针是常量,如下面情况。需要说明的是,由于没有const*这种含义解释,因此实际上上述两个式子其实是等价的。
int* const a=&b;
const int* const a=&b;
(2)const成员函数
const修饰成员函数时应该放在函数的后面,如int add(int a,int b) const;代表该成员函数不会修改类数据成员。
如果const关键字放在函数声明前,那么代表函数返回的值是const,即常量。
(3)如果在const成员函数中需要修改某些数据成员,应该怎么做?
可以在类数据成员用关键字mutable修饰,代表可修改。
(4)const和#define都可以定义常量,那么他们有什么不同呢?
const常量有数据类型,如const int a;而宏常量是没有数据类型的。编译器对const可以进行安全类型检查,而对后者值进行字符替换,没有类型安全检查。在c++中const只使用const常量,不使用宏常量。
3、sizeof
(1)先举几个例子,说明在sizeof上容易犯的错误。
char* ss1="0123"; sizeof(ss1)=4;
char ss2[]="0123"; sizeof(ss2)=5;
char ss3[100]="0123"; sizeof(ss3)=100;
int ss4[100]; sizeof(ss4)=400(100*4);
char q2[]="a\n"; sizeof(q2)=3;
char *q3="a\n"; sizeof(q3)=4;
char* str1=(char*) malloc(100); sizeof(str1)=4;
总结:
a、指针的大小为4字节。(指针的大小是由cpu的寻址位数决定的,32位cpu的32指的是字长,寻址位数不一定是32位)
b、char数组的大小已经给定,那么该数组的sizeof就是给定的大小。如果char数组的大小未给定,那么sizeof的结果将是给定值的个数+1,注意这里的加一代表字符串结束隐含的"\0"。即sizeof的大小是以访问到"\0"为依据的。
c、sizeof经常考察的还有一种情况是结构体,求结构体大小的时候一般遵循下面两条原则:
(I)结构体中成员的偏移量必须是成员类型大小的整数倍。(0是如何成员大小的整数倍)
(II)结构体是最大成员类型大小的整数倍。
举两个例子(假设处理器位数是32位):
struct A{
short a1;
short a2;
short a3;
};
那么sizeof(A)的大小是多少呢?2+2+2=6;查看上面两个原则。
struct B{
long a1;
short a2;
};
sizeof(B)=4+2+2(填充以满足第二个原则)=8;
题外话:在c++中可以通过pack预处理指令来禁止对齐调整。但是不推荐。
#pragma pack(1)
struct{...
};
#pragma pack()
需要注意的是:如果结构体中有静态变量,由于sizeof是计算栈中分配的大小,所以静态变量是不会计算在sizeof里面的。
4、sizeof和strlen都是求长度的,但是我们很容易将他们混淆,这里进行比较他们的不同。
char ss[100]="0123456789";
sizeof(ss)=100;
strlen(ss)=10;
总结:strlen内部实现是用一个循环计算字符串的长度,直到“\0”为止,但是不计算“\0”。
int s1[100];
strlen(s1)将会出错,这是因为strlen只针对char*类型的
a、sizeof是运算符,strlen是函数
b、数组传递给sizeof不退化,而传递给strlen就退化成指针
我们需要明确sizeof不是函数,也不是一元运算符,他是类似宏定义的特殊关键字,sizeof()。括号内的内容在编译过程中是不会被编译的,而是被替代类型。int a=8; cout<<sizeof(a=6);那么a的值将不会被改变,只是简单替代成sizeof(int)。
至于空类以及类继承等的情况,比较特殊,争取尽快将学习结果总结出来,共同进步。