本文是對《程序員面試寶典》的學習總結,不足之處望多多批評指正。
每次看《程序員面試寶典》都有收穫,但是不總結,有些東西無法真正掌握,這裏對預處理、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)。
至於空類以及類繼承等的情況,比較特殊,爭取儘快將學習結果總結出來,共同進步。