IT公司面試題總結五

2021-03-04 00:40:25 字數 6212 閱讀 5001

1.設一棵完全二叉樹有700個結點,則在該二叉樹中有多少個葉子結點

如果一棵具有n個結點的深度為k的二叉樹,它的每乙個結點都與深度為k的滿二叉樹中編號為1~n的結點一一對應,這棵二叉樹稱為完全二叉樹。

可以根據公式進行推導,假設n0是度為0的結點總數(即葉子結點數),n1是度為1的結點總數,n2是度為2的結點總數,由二叉樹的性質可知:n0=n2+1,則n=n0+n1+n2(其中n為完全二叉樹的結點總數),由上述公式把n2消去得:n=2n0+n1-1,由於完全二叉樹中度為1的結點數只有兩種可能0或1,由此得到n0=(n+1)/2或n0=n/2,合併成乙個公式:

n0=(n+1)/2,就可根據完全二叉樹的結點總數計算出葉子結點數。

700/2=350個葉子節點

2.static資料成員必須在類定義的外部定義。不象普通資料成員,static成員不是通過類建構函式進行初始化,而是應該在定義時進行初始化。

靜態資料成員的用途之一是統計有多少個物件實際存在。

靜態資料成員不能在類中初始化,實際上類定義只是在描述物件的藍圖,在其中指定初值是不允許的。也

不能在建構函式中初始化該成員,因為靜態資料成員為類的各個物件共享,那麼每次建立乙個類的物件則

靜態資料成員都要被重新初始化

#include

class a

//不注釋掉會出現鏈結錯誤

void foo()

private:

static int i;//如果換成static int i=10;出錯

};int a::i=10;//static變數在類外定義

void main()

3.求函式返回值,輸入x=9999;

intfunc(x)

return countx;

}結果呢?

知道了這是統計9999的二進位制數值中有多少個1的函式,且有

9999=9×1024+512+256+15

9×1024中含有1的個數為2;

512中含有1的個數為1;

256中含有1的個數為1;

15中含有1的個數為4;

故共有1的個數為8,結果為8。

1000-1=0111,正好是原數取反。這就是原理。

用這種方法來求1的個數是很效率很高的。

不必去乙個乙個地移位。迴圈次數最少。

4.分析下面的程式

struct s1

;struct s2

;printf("sizeof(s1)=%d\n",sizeof(s1));

printf("sizeof(s2)=%d\n",sizeof(s2));

result:16,24

第乙個struct s1

;理論上是這樣的,首先是i在相對0的位置,佔8位乙個位元組,然後,j就在相對乙個位元組的位置,由於乙個位置的位元組數是4位的倍數,因此不用對齊,就放在那裡了,然後是a,要在3位的倍數關係的位置上,因此要移一位,在15位的位置上放下,目前總共是18位,折算過來是2位元組2位的樣子,由於double是8位元組的,因此要在相對0要是8個位元組的位置上放下,因此從18位開始到8個位元組之間的位置被忽略,直接放在8位元組的位置了,因此,總共是16位元組。

1.乙個位域必須儲存在同乙個位元組中,不能跨兩個位元組。如乙個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

struct bs

在這個位域定義中,a佔第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,占用4位,c占用4位。

2.由於位域不允許跨兩個位元組,因此位域的長度不能大於乙個位元組的長度,也就是說不能超過8位二進位

3.位域可以無位網域名稱,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:

structk

;從以上分析可以看出,位域在本質上就是一種結構型別,不過其成員是按二進位分配的。

5.在對齊為4的情況下分析下面程式的結果

struct bbb

*p;p=0x1000000;

p+0x200=____;

(ulong)p+0x200=____;

(char*)p+0x200=____;

解答:假設在32位cpu上,

sizeof(long)=4bytes

sizeof(char*)=4bytes

sizeof(shortint)=sizeof(short)=2bytes

sizeof(char)=1bytes

由於是4位元組對齊,

sizeof(struct bbb)=sizeof(*p)

=4+4+2+1+1/*補齊*/+2*5+2/*補齊*/=24bytes(經dev-c++驗證)

p=0x1000000;

p+0x200=____;

=0x1000000+0x200*24指標加法,加出來的是指標型別的位元組長度的整倍數。就是p偏移sizeof(p)*0x200.

(ulong)p+0x200=____;

=0x1000000+0x200經過ulong後,這已經不再是指標加法,而變成乙個數值加法了

(char*)p+0x200=____;

=0x1000000+0x200*4結果型別是char*,這兒的1是char的資料型別是1位元組

6.分析一下下面程式的輸出結果

#include

#include

#include

#include

#include

#include

typedef struct aa

aa;voidmain()

答案:int **p;//二級指標

&arr;//得到的是指向第一維為100的陣列的指標

應該這樣寫#include

int main(void)

8.寫乙個記憶體拷貝函式,不用任何庫函式.

void *memcpy(void* pvto,const void* pvfrom,size_tsize)

return pvto;}}

9.將乙個數字字串轉換為數字."1234"-->1234

int convert(char*str)

return k;

}10.寫出執行結果

#include

#include

#define strcpy(a,b) strcpy(a##_p,#b)

#define strcpy1(a,b) strcpy(a##_p,b##_p)

int main(void)

答案:var1=bbbb

var2=var1

巨集中"#"和"##"的用法

一、一般用法

我們使用#把巨集引數變為乙個字串,用##把兩個巨集引數貼合在一起.

用法:#include

#include

using namespace std;

#define str(s) br##define cons(a,b) int(a##e##b)

int main()

二、當巨集引數是另乙個巨集的時候

需要注意的是凡巨集定義裡有用'#'或'##'的地方巨集引數是不會再展開.

1,非'#'和'##'的情況

#defi***ow (2)

#define mul(a,b) (a*b)

printf("%d*%d=%d\n",tow,tow,mul(tow,tow));

這行的巨集會被展開為:

printf("%d*%d=%d\n",(2),(2),((2)*(2)));

mul裡的引數tow會被展開為(2).

2,當有'#'或'##'的時候

#define a(2)

#define str(s) br##define cons(a,b) int(a##e##b)

printf("int max:%s\n",str(int_max));//int_max#include

這行會被展開為:

printf("int max:%s\n","int_max");

printf("%s\n",cons(a,a));//***pileerror

這一行則是:

printf("%s\n",int(aea));

a不會再被展開,然而解決這個問題的方法很簡單.加多一層中間轉換巨集.

加這層巨集的用意是把所有巨集的引數在這層裡全部展開,那麼在轉換巨集裡的那乙個巨集(_str)就能得到正確的

巨集引數.

#define a(2)

#define _str(s) br##define str(s) _ str(s)//轉換巨集

#define _cons(a,b) int(a##e##b)

#define cons(a,b) _cons(a,b)//轉換巨集

printf("int max:%s\n",str(int_max));//int_max,int型的最大值,為乙個變數

#include

輸出為:int max:0x7fffffff

str(int_max)-->_str(0x7fffffff)然後再轉換成字串;

printf("%d\n",cons(a,a));

輸出為:200

cons(a,a)-->_cons((2),(2))-->int((2)e(2))

11:此題考查的是c的變長引數,就像標準函式庫裡printf()那樣.

#include

int ripple(int,...);

main()

int ripple(int n,...)

return k;

}這段程式的輸出是:

(a)7

(b)6

(c)5

(d)3

答案:(c)

在c編譯器通常提供了一系列處理可變引數的巨集,以遮蔽不同的硬體平台造成的差異,增加程式的可移性。這些巨集包括va_start、va_arg和va_end等。

採用ansi標準形式時,引數個數可變的函式的原型宣告是:

typdef un**ame(typepara1,typepara2,...)

這種形式至少需要乙個普通的形式引數,後面的省略號不表示省略,而是函式原型的一部分。type是函式返回值和形式引數的型別。

不同的編譯器,對這個可變長引數的實現不一樣,gcc4.x中是內建函式.

關於可變長引數,可參閱

程式分析

va_list p;/*定義乙個變數,儲存函式引數列表的指標*/

va_start(p,n);/*用va_start巨集初始化變數p,va_start巨集的第2個引數n,是乙個固定的引數,

必須是我們自己定義的變長函式的最後乙個入棧的引數也就是呼叫的時候引數列表裡的第1個引數*/

for(;j

當我們呼叫ripple函式時,傳遞給ripple函式的引數列表的第乙個引數n的值是3.

va_start初始化p指向第乙個未命名的引數(n是有名字的引數),也就是is5(第乙個).

每次對va_arg的呼叫,都將返回乙個引數,並且把p指向下乙個引數.

va_arg用乙個型別名來決定返回的引數是何種型別,以及在var_arg的內部實現中決定移動多大的距離才

到達下乙個引數

(;i;i&=i-1)k++/*計算i有多少bit被置1*/

5用二進位制表示是(101)2

7用二進位制表示(111)3

所以k返回5(2+3),也即本題應該選c

因為i與i-1的最右邊的那位(最低位)肯定是不同,如果i1,i-1肯定是0,反之亦然.i&i-1這個運算,在二相補的數字系統中,將會消除最右邊的1位

12.要對絕對位址0x100000賦值,我們可以用(unsignedint*)0x100000=1234;

那麼要是想讓程式跳轉到絕對位址是0x100000去執行,應該怎麼做?

答案:*((void(*)())0x100000)();

首先要將0x100000強制轉換成函式指標,即:

(void(*)())0x100000

然後再呼叫它:

*((void(*)())0x100000)();

用typedef可以看得更直觀些:

typedef void(*)() void func ptr;

*((void func ptr)0x100000)();

13.c++中為什麼用模板類。

答:(1)可用來建立動態增長和減小的資料結構

(2)它與型別無關,因此具有很高的可復用性。

(3)它在編譯時而不是執行時檢查資料型別,保證了型別安全

(4)它是平台無關的,可移植性

(5)可用於基本資料型別

總結面試題

面試題小總結 1 在hibernate 中的配置中 現在有animal 類 dog 類 cat 類 dog cat 分別繼承 animal 請問 設計資料表中,應該設計幾張表,假如設計一第表的話,怎麼區分 dog cat 2 在多執行緒中,怎麼使兩個執行緒共同使用乙個成員變數 3 有乙個物件 a 我...

經典c 面試題五

46 位域 有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,語言又提供了一種資料結構,稱為 位域 或 位段 所謂 位域 是把乙個位元組中的二進位劃分為幾個不同的區域,並說明每...

遊戲公司unity面試題

unity3d 程式設計師面試題 1.什麼是渲染管道?渲染管道有哪些步驟?答 渲染管道是指程式為了在顯示器上輸出影象而經過的一系列必要操作.渲染管道的步驟有 本地空間 世界空間 檢視空間 背面剔除 光照計算 相機裁剪 投影計算 視口變換 光柵化 2.unity3d有幾種載入prefab的方式?答 1...