程序員面試(c++)——預處理,const與sizeof總結

本文是對《程序員面試寶典》的學習總結,不足之處望多多批評指正。

每次看《程序員面試寶典》都有收穫,但是不總結,有些東西無法真正掌握,這裏對預處理、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)。

至於空類以及類繼承等的情況,比較特殊,爭取儘快將學習結果總結出來,共同進步。




發佈了65 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章