IGT中国
1、calloc,malloc 和 alloca的區(qū)別;
答案:
內(nèi)存區(qū)域可以分為棧、堆、靜態(tài)存儲區(qū)和常量存儲區(qū),局部變量,函數(shù)形參,臨時變量都是在棧上獲得內(nèi)存的,它們獲取的方式都是由編譯器自動執(zhí)行的。
? ? 利用指針,我們可以像匯編語言一樣處理內(nèi)存地址,C 標(biāo)準(zhǔn)函數(shù)庫提供了許多函數(shù)來實現(xiàn)對堆上內(nèi)存管理,其中包括:malloc函數(shù),free函數(shù),calloc函數(shù)和realloc函數(shù)。使用這些函數(shù)需要包含頭文件stdlib.h。
? ? 四個函數(shù)之間的有區(qū)別,也有聯(lián)系,我們應(yīng)該學(xué)會把握這種關(guān)系,從而編出精煉而高效的程序。
? ? 在說明它們具體含義之前,先簡單從字面上加以認識,前3個函數(shù)有個共同的特點,就是都帶有字符”alloc”,就是”allocate”,”分配”的意 思,也就是給對象分配足夠的內(nèi)存,” calloc()”是”分配內(nèi)存給多個對象”,” malloc()”是”分配內(nèi)存給一個對象”,”realloc()”是”重新分配內(nèi)存”之意。”free()”就比較簡單了,”釋放”的意思,就是把之 前所分配的內(nèi)存空間給釋放出來。
void *calloc(size_t nobj, size_t size);
分配足夠的內(nèi)存給nobj個大小為size的對象組成的數(shù)組, 并返回指向所分配區(qū)域的第一個字節(jié)的指針;若內(nèi)存不夠,則返回NULL. 該空間的初始化大小為0字節(jié).char *p = (char *) calloc(100,sizeof(char));
void *malloc(size_t size);
分配足夠的內(nèi)存給大小為size的對象, 并返回指向所分配區(qū)域的第一個字節(jié)的指針;若內(nèi)存不夠,則返回NULL. 不對分配的空間進行初始化.char *p = (char *)malloc(sizeof(char));
void *realloc(void *p, size_t size);
將p所指向的對象的大小改為size個字節(jié).如果新分配的內(nèi)存比原內(nèi)存大, 那么原內(nèi)存的內(nèi)容保持不變, 增加的空間不進行初始化.如果新分配的內(nèi)存比原內(nèi)存小, 那么新內(nèi)存保持原內(nèi)存的內(nèi)容, 增加的空間不進行初始化.返回指向新分配空間的指針; 若內(nèi)存不夠,則返回NULL, 原p指向的內(nèi)存區(qū)不變.
char *p = (char *)malloc(sizeof(char));
p= (char *)realloc(p, 256);
void free(void *p);
釋放p所指向的內(nèi)存空間; 當(dāng)p為NULL時, 不起作用.p必先調(diào)用calloc, malloc或realloc.
值得注意的有以下5點:
(1)通過malloc函數(shù)得到的堆內(nèi)存必須使用memset函數(shù)來初始化malloc函數(shù)分配得到的內(nèi)存空間是未初始化的。因此,一般在使用該內(nèi)存空間 時,要調(diào)用另一個函數(shù)memset來將其初始化為全0,memset函數(shù)的聲明如下:void * memset (void * p,int c,int n) ;
該函數(shù)可以將指定的內(nèi)存空間按字節(jié)單位置為指定的字符c,其中,p為要清零的內(nèi)存空間的首地址,c為要設(shè)定的值,n為被操作的內(nèi)存空間的字節(jié)長度。如果要用memset清0,變量c實參要為0。
malloc函數(shù)和memset函數(shù)的操作語句一般如下:
int * p=NULL;
p=(int*)malloc(sizeof(int));
if(p==NULL)
? ? printf(“Can’t get memory!\n”);
memset(p,0,siezeof(int));
(2)使用malloc函數(shù)分配的堆空間在程序結(jié)束之前必須釋放
從堆上獲得的內(nèi)存空間在程序結(jié)束以后,系統(tǒng)不會將其自動釋放,需要程序員來自己管理。一個程序結(jié)束時,必須保證所有從堆上獲得的內(nèi)存空間已被安全釋放,否 則,會導(dǎo)致內(nèi)存泄露。我們可以使用free()函數(shù)來釋放內(nèi)存空間,但是,free函數(shù)只是釋放指針指向的內(nèi)容,而該指針仍然指向原來指向的地方,此時, 指針為野指針,如果此時操作該指針會導(dǎo)致不可預(yù)期的錯誤。安全做法是:在使用free函數(shù)釋放指針指向的空間之后,將指針的值置為NULL。
(3)calloc函數(shù)的分配的內(nèi)存也需要自行釋放calloc函數(shù)的功能與malloc函數(shù)的功能相似,都是從堆分配內(nèi)存,它與malloc函數(shù)的一個 顯著不同時是,calloc函數(shù)得到的內(nèi)存空間是經(jīng)過初始化的,其內(nèi)容全為0。calloc函數(shù)適合為數(shù)組申請空間,可以將size設(shè)置為數(shù)組元素的空間 長度,將n設(shè)置為數(shù)組的容量。
(4)如果要使用realloc函數(shù)分配的內(nèi)存,必須使用memset函數(shù)對其內(nèi)存初始化realloc函數(shù)的功能比malloc函數(shù)和calloc函數(shù) 的功能更為豐富,可以實現(xiàn)內(nèi)存分配和內(nèi)存釋放的功能。realloc 可以對給定的指針?biāo)傅目臻g進行擴大或者縮小,無論是擴張或是縮小,原有內(nèi)存的中內(nèi)容將保持不變。當(dāng)然,對于縮小,則被縮小的那一部分的內(nèi)容會丟失。 realloc 并不保證調(diào)整后的內(nèi)存空間和原來的內(nèi)存空間保持同一內(nèi)存地址。相反,realloc 返回的指針很可能指向一個新的地址。所以,在代碼中,我們必須將realloc返回的值,重新賦值給 p :
p = (int *) realloc(p, sizeof(int) *15);
甚至,你可以傳一個空指針(0)給 realloc ,則此時realloc 作用完全相當(dāng)于malloc。
int* p = (int *)realloc (0,sizeof(int) * 10); ? //分配一個全新的內(nèi)存空間,
這一行,作用完全等同于:
int* p = (int *)malloc(sizeof(int) * 10);
(5)關(guān)于alloca()函數(shù)
還有一個函數(shù)也值得一提,這就是alloca()。其調(diào)用序列與malloc相同,但是它是在當(dāng)前函數(shù)的棧幀上分配存儲空間,而不是在堆中。其優(yōu)點是:當(dāng) 函數(shù)返回時,自動釋放它所使用的棧幀,所以不必再為釋放空間而費心。其缺點是:某些系統(tǒng)在函數(shù)已被調(diào)用后不能增加棧幀長度,于是也就不能支持alloca 函數(shù)。盡管如此,很多軟件包還是使用alloca函數(shù),也有很多系統(tǒng)支持它。
2、刪除平衡二叉樹中的一個節(jié)點;
3、static_cast 和 dynamaic_cast 的用法。
代碼如下:
1 #include <iostream> 2 3 using namespace std; 4 5 6 class Base 7 { 8 public: 9 Base(){} 10 ~Base(){} 11 virtual void Output(int i) 12 { 13 cout<<"Base::Output value is "<<i<<endl; 14 } 15 }; 16 17 class Derived1:public Base 18 { 19 public: 20 Derived1(){} 21 ~Derived1(){} 22 23 virtual void Output(int i) 24 { 25 cout<<"Derived1::Output value is "<<i<<endl; 26 } 27 28 void Output2() 29 { 30 cout<<"Dervied1:Output2"<<endl; 31 } 32 33 }; 34 35 class Dervied2:public Base 36 { 37 public: 38 Dervied2(){} 39 ~Dervied2(){} 40 virtual void Output(int i) 41 { 42 cout<<"Dervied2::Output value is "<<i<<endl; 43 } 44 45 void Output2() 46 { 47 cout<<"Dervied2:Output2"<<endl; 48 } 49 }; 50 51 52 53 int main() 54 { 55 Base *p= new Dervied2; 56 Derived1 *p1= static_cast<Derived1*>(p); 57 if(p1) 58 { 59 p1->Output(1); 60 p1->Output2(); 61 } 62 cout<<"=========================\n"; 63 64 p1= dynamic_cast<Derived1*>(p); 65 if(p1) 66 { 67 p1->Output(2); 68 p1->Output2(); 69 } 70 71 system("pause"); 72 }轉(zhuǎn)自:http://www.cnblogs.com/cswolf/archive/2011/10/13/2267127.html
轉(zhuǎn)載于:https://www.cnblogs.com/heyonggang/archive/2012/12/13/2817116.html
總結(jié)
- 上一篇: UDP穿越NAT原理
- 下一篇: 信息编码:位操作布尔值编码