有關C/C++的一些基礎知識

1.多態類中的虛函數表是Compile-Time,還是Run-Time時建立的?

答案:虛擬函數表是在編譯期就建立了,各個虛擬函數這時被組織成了一個虛擬函數的入口地址的數組.而對象的隱藏成員--虛擬函數表指針是在運行期--也就是構造函數被調用時進行初始化的,這是實現多態的關鍵.


2.一個父類寫了一個virtual 函數,如果子類覆蓋它的函數不加virtual ,也能實現多態?在子類的空間裏,有沒有父類的這個函數,或者父類的私有變量?

答案:只要基類在定義成員函數時已經聲明瞭virtue關鍵字,在派生類實現的時候覆蓋該函數時,virtue關鍵字可加可不加,不影響多態的實現。子類的空間裏有父類的所有變量(static除外)


3.完成字符串拷貝可以使用 sprintf、strcpy 及 memcpy 函數,請問這些函數有什麼區別

答案:這些函數的區別在於 實現功能 以及 操作對象 不同。
1.strcpy 函數操作的對象是 字符串,完成 從 源字符串目的字符串拷貝 功能。
2.sprintf 函數操作的對象不限於字符串:雖然目的對象是字符串,但是源對象可以是字符串、也可以是任意基本類型的數據。這個函數主要用來實現(字符串或基本數據類型)向字符串的轉換功能。如果源對象是字符串,並且指定 %s 格式符,也可實現字符串拷貝功能。
3.memcpy 函數顧名思義就是 內存拷貝,實現 將一個 內存塊 的內容複製到另一個 內存塊 這一功能。內存塊由其首地址以及長度確定。程序中出現的實體對象,不論是什麼類型,其最終表現就是在內存中佔據一席之地(一個內存區間或塊)。因此,memcpy 的操作對象不侷限於某一類數據類型,或者說可適用於任意數據類型,只要能給出對象的起始地址和內存長度信息、並且對象具有可操作性即可。鑑於 memcpy 函數等長拷貝的特點以及數據類型代表的物理意義,memcpy 函數通常限於同種類型數據或對象之間的拷貝,其中當然也包括字符串拷貝以及基本數據類型的拷貝。

對於字符串拷貝來說,用上述三個函數都可以實現,但是其實現的效率和使用的方便程度不同:

  • strcpy 無疑是最合適的選擇:效率高且調用方便。
  • snprintf 要額外指定格式符並且進行格式轉化,麻煩且效率不高。
  • memcpy 雖然高效,但是需要額外提供拷貝的內存長度這一參數,易錯且使用不便;並且如果長度指定過大的話(最優長度是源字符串長度 + 1),還會帶來性能的下降。其實 strcpy 函數一般是在內部調用 memcpy函數或者用匯編直接實現的,以達到高效的目的。因此,使用 memcpy 和 strcpy 拷貝字符串在性能上應該沒有什麼大的差別。

對於非字符串類型的數據的複製來說,strcpy 和 snprintf 一般就無能爲力了,可是對 memcpy 卻沒有什麼影響。但是,對於基本數據類型來說,儘管可以用 memcpy 進行拷貝,由於有賦值運算符可以方便且高效地進行同種或兼容類型的數據之間的拷貝,所以這種情況下 memcpy 幾乎不被使用。memcpy 的長處是用來實現(通常是內部實現居多)對結構或者數組的拷貝,其目的是或者高效,或者使用方便,甚或兩者兼有。


4.變量的聲明和定義有什麼區別

聲明是向編譯器介紹名字--標識符。它告訴編譯器“這個函數或變量在某處可找到,它的模樣象什麼”。而定義是說:“在這裏建立變量”或“在這裏建立函數”。它爲名字分配存儲空間。無論定義的是函數還是變量,編譯器都要爲它們在定義點分配存儲空間。對於變量,編譯器確定變量的大小,然後在內存中開闢空間來保存其數據,對於函數,編譯器會生成代碼,這些代碼最終也要佔用一定的內存。  

  在C和C++中,可以在不同的地方聲明相同的變量和函數,但只能有一個定義(有時這稱爲ODR,單一定義規則)。。。  

  定義也可以是聲明,如果有int   x;,之前編譯器未發現標識符x,編譯器則把這一標識符看成是定義並立即爲它分配存儲空間。  

  。。。。。  

  對“變量聲明”的解釋向來模糊且自相矛盾。。

  函數聲明包括函數類型、函數名、參數列表和一個分號,這些信息足以編譯器認出它是一個函數聲明並可識別出這個函數的外部特徵。由此推斷,變量聲明應是類型標識後面跟一個標識符。如int   a;但這產生了一個矛盾,這段代碼有足夠的信息讓編譯器爲之分配存儲空間,而且編譯器也確實給之分配了存儲空間。要解決這個問題,對於C和C++需要一個關鍵字來說明“這是一個聲明,它的定義在別的地方”,這個關鍵字就是extern,它表示變量是在文件以外定義的,或在文件後面定義的。  

  在變量定義前加extern表示聲明一個變量但不定義它,如:  

 extern   int   a;  

 extern也可用於函數聲明,如:  

 extern   int   func1(int  length,int   width);  

  但由於沒有函數體,編譯器必把它當成聲明而非定義,extern對於函數來說是多餘的、可選的。C語言的設計者並不要求函數聲明使用extern,這可能有些令人遺憾,如果函數聲明也要求用extern,那麼形式上與變量聲明更加一致了,從而減少了混亂(但這就需要更多的輸入,這也許能解釋爲什麼不要求函數聲明使用extern的原因)。


5.字符指針、浮點數指針、以及函數指針這三種類型的變量哪個佔用的內存最大?爲什麼?

答案:指針變量也佔用內存單元,而且所有指針變量佔用內存單元的數量都是相同的。就是說,不管是指向何種對象的指針變量,它們佔用內存的字節數都是一樣的,並且要足夠把程序中所能用到的最大地址表示出來(通常是一個機器字長)。

6.同步機制應該遵循哪些基本準則?

1.空閒讓進 2.忙則等待3.有限等待4.讓權等待


7.各種類型32位或者64位的編譯器下所佔用的字節數

32位編譯器
char 1個字節
char*
(即指針變量): 4個字節(32位的尋址空間是2^32,32bit,也就是4個字節。同理64位編譯器)
short int : 2
個字節
int
 4個字節
unsigned int : 4
個字節
float:  4
個字節
double:   8
個字節
long:   4
個字節
long long:  8
個字節
unsigned long:  4
個字節

64位編譯器
char
1個字節
char*(
即指針變量): 8個字節
short int : 2
個字節
int
 4個字節
unsigned int : 4
個字節
float:  4
個字節
double:   8
個字節
long:   8
個字節
long long:  8
個字節
unsigned long:  8
個字節

8.

char * GetStr()
{
    char *tmp;
    tmp = "123"
    return tmp;
}
void main()
{
    printf("%s", GetStr());
}
會輸出123嗎?123創建在堆上還是棧上呢?123的空間是什麼時候釋放的?
會,"123" 是常量字符串,存儲在全局變量區,和靜態變量一起。即不在堆,也不在棧 在程序結束時自動釋放

9.應用程序在運行時的內存包括代碼區和數據區,其中數據區又包括哪些部分?

參考:對於一個進程的內存空間而言,可以在邏輯上分成3個部份:代碼區,靜態數據區和動態數據區。動態數據區一般就是“堆棧”。棧是一種線性結構,堆是一種鏈式結構。進程的每個線程都有私有的“棧”。全局變量和靜態變量分配在靜態數據區,本地變量分配在動態數據區,即堆棧中。程序通過堆棧的基地址和偏移量來訪問本地變量

10.用<<,>>,|,&實現一個WORD(2個字節)的高低位交換!!

int  main() 
{ 
	unsigned  short  a  =  0xABCD; 
	unsigned  short  b  ; 
	unsigned  short  c  ,d; 
	b  =  (a  <<  8)&0xff00;   
	c  =  (a  >>  8)&0x00ff; 
	d  =  b  |  c; 
	printf("\n%x",a);
	printf("\n%x",b); 
	printf("\n%x",c); 
	printf("\n%x\n",d); 
	return  0; 
}
結果是  CDAB   
2倆個字節是16位  前八位爲高位  後八位爲低位  然後結合

11.寫出運行結果

int sum(int a)
{ auto int c=0;		//自動變量,值都會初始化
  static int b=3;	//靜態變量,值不會初始化
c+=1;
b+=2;
return(a+b+c);
}
void main()
{ int i;
int a=2;
for(i=0;i<5;i++)
{ printf("%d,", sum(a));}
}
8,10,12,14,16

12.

9:某進程在運行過程中需要等待從磁盤上讀入數據,此時進程的狀態將:C

A: 從就緒變爲運行  B:從運行變爲就緒

C: 從運行變爲阻塞  D:從阻塞變爲就緒

解析:
  • 運行狀態(Running):進程佔用處理器資源;處於此狀態的進程的數目小於等於處理器的數目。在沒有其他進程可以執行時(如所有進程都在阻塞狀態),通常會自動執行系統的空閒進程。
  • 就緒狀態(Ready):進程已獲得除處理器外的所需資源,等待分配處理器資源;只要分配了處理器進程就可執行。就緒進程可以按多個優先級來劃分隊列。例如,當一個進程由於時間片用完而進入就緒狀態時,排人低優先級隊列;當進程由I/O操作完成而進入就緒狀態時,排入高優先級隊列
  • 阻塞狀態(Blocked):當進程由於等待I/O操作或進程同步等條件而暫停運行時,它處於阻塞狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章