天天看點

C/C++經典面試50題(挑重點整理)上

面試題3:sizeof和strlen的差別

sizeof和strlen有以下差別:

sizeof是一個操作符,strlen是庫函數。

sizeof的參數可以是資料的類型,也可以是變量,而strlen隻能以結尾為‘0‘的字元串作參數。

編譯器在編譯時就計算出了sizeof的結果。而strlen函數必須在運作時才能計算出來。并且sizeof計算的是資料類型占記憶體的大小,而strlen計算的是字元串實際的長度。

數組做sizeof的參數不退化,傳遞給strlen就退化為指針了。

注意:有些是操作符看起來像是函數,而有些函數名看起來又像操作符,這類容易混淆的名稱一定要加以區分,否則遇到數組名這類特殊資料類型作參數時就很容易出錯。最容易混淆為函數的操作符就是sizeof。

strlen()與sizeof()考點,一步到位!

看下msdn的官方解釋:

Strlen——Get the length of a string.

size_t strlen( const char *string );

Each ofthese functions returns the number of characters instring, notincluding the terminating null character.           

函數傳回string裡的字元數,不包括終止字元’0’。

sizeof Operator 運算符

sizeofexpression

The sizeofkeyword gives the amount of storage, in bytes, associated with a variable or atype (including aggregate types). This keyword returns a value of typesize_t.

//傳回變量或類型(包括集合類型)存儲空間的大小,
 
The expressionis either an identifier or a type-cast expression (a type specifier enclosed inparentheses).

When appliedto a structure type or variable,sizeof returns the actual size, whichmay include padding bytes inserted for alignment. When applied to a staticallydimensioned array,sizeof returns the size of the entire array. The sizeofoperator cannot return the size of dynamically allocated arrays or externalarrays.           

//應用結構體類型或變量的時候,sizeof()傳回事實的大小,包括為對齊而填充位元組。當應用到靜态數組時,sizeof()傳回整個數組的大小。sizeof()不會傳回動态配置設定數組或擴充數組的大小。

char str[] = “Hello” ;

char *p = str ;

int n = 10;
 
請計算

sizeof (str) =  //5+1=6 ,注意1代表'\0'容易落下,代表結束符。 str所占據的存儲空間大小

sizeof ( p )=  //4指針類型

sizeof ( n )=  //4整形占據的存儲空間

void Func ( char str[100])

{
 
請計算
 
sizeof( str ) = //4此時str轉化為指針大小仍為4


}
 
void *p = malloc( 100 );

請計算

sizeof ( p ) =  //4指針大小4           

面試題5:C中的malloc和C++中的new有什麼差別

malloc和new有以下不同:

(1)new、delete是操作符,可以重載,隻能在C++中使用。

(2)malloc、free是函數,可以覆寫,C、C++中都可以使用。

(3)new可以調用對象的構造函數,對應的delete調用相應的析構函數。

(4)malloc僅僅配置設定記憶體,free僅僅回收記憶體,并不執行構造和析構函數

(5)new、delete傳回的是某種資料類型指針,malloc、free傳回的是void指針。

注意:malloc申請的記憶體空間要用free釋放,而new申請的記憶體空間要用delete釋放,不要混用。因為兩者實作的機理不同。

面試題8:a和&a有什麼差別

請寫出以下代碼的列印結果,主要目的是考察a和&a的差別。

#include<stdio.h>

void main( void)

{

  inta[5]={1,2,3,4,5};

  int*ptr=(int *)(&a+1); //此處&a是數組的指針,1實際1個數組長度 1*5*4 = 20個位元組;

  int*ptr2 = (int *)(a+1);

  printf("%d,%d\n",*(a+1),*(ptr-1));  //

  printf("%d,%d\n",*(a+1),*(ptr2-1));


}                

注意:數組名a可以作數組的首位址,而&a是數組的指針。對比上兩式子的不同。

&a+1,&a為代表a數組的指針,1根據&a變化代表了int a[5]數組的大小,為4*5=20個位元組。

a+1,  a代表數組a的首位址,1代表數組a中1個元素的長度,為4個位元組。

int ptr = (int )(&a + 1),代表ptr指向a數組20個位元組後的一塊記憶體區域,顯然,該記憶體區域未定義,為一個随機值。而(ptr-1),此處ptr減去14個位元組長度,ptr-1指向a[5],*(ptr-1)=a[5];

而int ptr2 = (int )(a+1),代表指向數組首位址14個位元組後元素,即a[1] = 2;即ptr2指向a[2],此處的a = (a+0) = a[0], (a+1) = a[1],依次類推。

面試題9:簡述C、C++程式編譯的記憶體配置設定情況

C、C++中記憶體配置設定方式可以分為三種:

(1)從靜态存儲區域配置設定:

記憶體在程式編譯時就已經配置設定好,這塊記憶體在程式的整個運作期間都存在。速度快、不容易出錯,因為有系統會善後。例如全局變量,static變量等。

(2)在棧上配置設定:

在執行函數時,函數内局部變量的存儲單元都在棧上建立,函數執行結束時這些存儲單元自動被釋放。棧記憶體配置設定運算内置于處理器的指令集中,效率很高,但是配置設定的記憶體容量有限。

工作中讨論問題都叫棧變量。

(3)從堆上配置設定:

即動态記憶體配置設定。程式在運作的時候用malloc或new申請任意大小的記憶體,程式員自己負責在何時用free或delete釋放記憶體。動态記憶體的生存期由程式員決定,使用非常靈活。如果在堆上配置設定了空間,就有責任回收它,否則運作的程式會出現記憶體洩漏,另外頻繁地配置設定和釋放不同大小的堆空間将會産生堆内碎塊。

一個C、C++程式編譯時記憶體分為5大存儲區:堆區、棧區、全局/靜态區、文字常量(字元常量)區、程式代碼區。

面試題11:設定位址為0x67a9的整型變量的值為0xaa66

int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa66;           

說明:這道題就是強制類型轉換的典型例子,無論在什麼平台位址長度和整型資料的長度是一樣的,即一個整型資料可以強制轉換成位址指針類型,隻要有意義即可。

但是,此處的轉換,編譯沒有問題,但是運作的時候可能會出錯。因為Ox67a9這塊位址可能被占用……

面試題13:C++的空類有哪些成員函數

       1)預設構造函數。

       2)預設拷貝構造函數。

       3)預設析構函數。

       4)預設指派運算符。

       5)預設取址運算符。

       6)預設取址運算符 const。

注意:有些書上隻是簡單的介紹了前四個函數。沒有提及後面這兩個函數。但後面這兩個函數也是空類的預設函數。另外需要注意的是,隻有當實際使用這些函數的時候,編譯器才會去定義它們。

面試題14:談談你對拷貝構造函數和指派運算符的認識

拷貝構造函數和指派運算符重載有以下兩個不同之處:

(1)拷貝構造函數生成新的類對象,而指派運算符不能。

(2)由于拷貝構造函數是直接構造一個新的類對象,是以在初始化這個對象之前不用檢驗源對象是否和建立對象相同。而指派運算符則需要這個操作,另外指派運算中如果原來的對象中有記憶體配置設定要先把記憶體釋放掉

注意:當有類中有指針類型的成員變量時,一定要重寫拷貝構造函數和指派運算符,不要使用預設的。

面試題15:用C++設計一個不能被繼承的類

class A

{

private:

A() {}

~A() {}

};

class B : virtual public A

{

public:

        B(){}

        ~B(){}

};

class C : virtual public B

{

public:

  C() {}

  ~C() {}

};

void main( void )

{

B b;

//C c;

return;

}           

注意:構造函數是繼承實作的關鍵,每次子類對象構造時,首先調用的是父類的構造函數,然後才是自己的。

此處,如果将父類構造函數寫成私有的,便不能完成繼承操作。這是考察點。

待完善!加油!2012/7/27 向原作者緻敬!

感謝網友shunqiziranhao007 的指正!

作者:銘毅天下

原文:

https://blog.csdn.net/laoyang360/article/details/7795610

版權聲明:本文為部落客原創文章,轉載請附上博文連結!

繼續閱讀