對C語言一直都是抱着學習的態度,不少都不懂,今天忽然被問道C語言的內存分配問題,說了一些本身知道的,但感受回答的並不完善,因此纔有這篇筆記,總結一下C語言中內存分配的主要內容。程序員
剛剛在一篇博文看到一個簡單的問題:
數組
//code1 char* toStr() { char *s = "abcdefghijkl"; return s; } int main() { cout << toStr() << endl; return 0; } //code2 char* toStr() { char s[] = "abcdefghijkl"; return s; } int main() { cout << toStr() << endl; return 0; }
兩段代碼都很簡單,輸出一段字符,類型不一樣,一個是char*字符串,一個是char[]數據。數據結構
結果你知道嗎? 這個我確實知道,相信大部分人也都回知道,必然有一個很差使,或者兩個都很差使!!!都對就沒意思了~函數
結果:第一個正確輸出,第二個輸出亂碼。學習
緣由:在於局部變量的做用域和內存分配的問題,第一char*是指向一個常量,做用域爲函數內部,被分配在程序的常量區,直到整個程序結束才被銷燬,因此在程序結束前常量仍是存在的。而第二個是數組存放的,做用域爲函數內部,被分配在棧中,就會在函數調用結束後被釋放掉,這時你再調用,確定就錯誤了。優化
什麼是局部變量、全局變量和靜態變量?spa
顧名思義,局部變量就是在一個有限的範圍內的變量,做用域是有限的,對於程序來講,在一個函數體內部聲明的普通變量都是局部變量,局部變量會在棧上申請空間,函數結束後,申請的空間會自動釋放。而全局變量是在函數體外申請的,會被存放在全局(靜態區)上,知道程序結束後纔會被結束,這樣它的做用域就是整個程序。靜態變量和全局變量的存儲方式相同,在函數體內聲明爲static就可使此變量像全局變量同樣使用,不用擔憂函數結束而被釋放。.net
void *malloc(size_t size); void free(void *p); /*通常這樣用 Struct elem *p; p = (struct elem*)malloc(sizeof(struct elem)) void free(p) */
malloc函數的實質體如今,它有一個將可用的內存塊鏈接爲一個長長的列表的所謂空閒鏈表。調用malloc函數時,它沿鏈接表尋找一個大到足以知足用戶請求所須要的內存塊。而後,將該內存塊一分爲二(一塊的大小與用戶請求的大小相等,另外一塊的大小就是剩下的字節)。接下來,將分配給用戶的那塊內存傳給用戶,並將剩下的那塊(若是有的話)返回到鏈接表上。調用free函數時,它將用戶釋放的內存塊鏈接到空閒鏈上。到最後,空閒鏈會被切成不少的小內存片斷,若是這時用戶申請一個大的內存片斷,那麼空閒鏈上可能沒有能夠知足用戶要求的片斷了。因而,malloc函數請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各內存片斷,對它們進行整理,將相鄰的小空閒塊合併成較大的內存塊。若是沒法得到符合要求的內存塊,malloc函數會返回NULL指針,所以在調用malloc動態申請內存塊時,必定要進行返回值的判斷。指針
//main.cpp int a = 0; //全局初始化區 char *p1; //全局未初始化區 main() { int b; //棧 char s[] = "abc"; //棧 char *p2; //棧 char *p3 = "123456"; //123456\\0在常量區,p3在棧上。 static int c =0;//全局(靜態)初始化區 p1 = (char *)malloc(10); p2 = (char *)malloc(20);//分配得來得10和20字節的區域就在堆區。 strcpy(p1, "123456"); //123456\\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。 }
此外,還有realloc(從新分配內存)、calloc(初始化爲0)、alloca(在棧上申請內存,自動釋放)等。code