C語言深入講解動態(tài)內(nèi)存分配函數(shù)的使用
局部變量和函數(shù)的形參向棧區(qū)申請空間
全局變量和static靜態(tài)變量向靜態(tài)區(qū)申請空間
動態(tài)內(nèi)存分配向堆區(qū)申請空間(位于<stdlib.h>或<cstdlib>頭文件)
一、malloc
void* malloc (size_t size);
分配內(nèi)存塊
分配一個連續(xù)可用的字節(jié)內(nèi)存塊,返回指向該內(nèi)存塊開頭的指針。
新分配的內(nèi)存塊的內(nèi)容未初始化,內(nèi)存塊中的數(shù)據(jù)為不確定值。
如果為參數(shù)為零,則返回值取決于特定的庫實現(xiàn)(它可能是空指針,也可能不是空指針)。
參數(shù)
內(nèi)存塊的大小,以字節(jié)為單位。
是無符號整數(shù)類型,size_t。
返回值
成功時,為指向函數(shù)分配的內(nèi)存塊的指針。
此指針的類型始終為void*,可以將其轉(zhuǎn)換為所需的數(shù)據(jù)指針類型。(C++由于其類型檢查更為嚴格,則必須進行強制類型轉(zhuǎn)換)
如果函數(shù)未能分配請求的內(nèi)存塊,則返回空指針NULL。
#include<stdlib.h> #include<string.h> #include<errno.h> #include<stdio.h> int main() { int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { printf("%s\n", strerror(errno)); } else { for (int i = 0; i < 10; ++i) { *(p + i) = i; } for (int i = 0; i < 10; ++i) { printf("%d ", *(p + i)); } } free(p); p = NULL; /* 1.斷開指針與動態(tài)開辟的空間的聯(lián)系,避免指針的危險操作 2.防止對同一塊動態(tài)空間內(nèi)存空間的重復(fù)釋放 */ return 0; }
輸出
0 1 2 3 4 5 6 7 8 9
二、free(用于釋放動態(tài)開辟的空間)
void free(void* ptr);
解除分配內(nèi)存塊
1.若參數(shù)ptr指向的空間不是動態(tài)開辟的,那么free函數(shù)的行為是未定義的。
2.若參數(shù)ptr是NULL指針,則free函數(shù)什么也不做。
3.free只釋放堆區(qū)空間,但ptr仍指向那塊空間。所以使用完free后要將ptr置為NULL,切斷ptr與該內(nèi)存塊的聯(lián)系。
參數(shù)
指向要釋放的那塊空間的指針(必須指向初始位置)
返回值
無
錯誤案例
#include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)malloc(sizeof(int) * 10); if (p == NULL) { return 1; } for (int i = 0; i < 10; ++i) { *(p + i) = i; } for (int i = 0; i < 10; ++i) { printf("%d ", *(p++));//這里指針移動 } free(p);//導(dǎo)致free釋放的不是初始位置的指針,程序崩潰 p = NULL; return 0; }
三、calloc
void* calloc(size_t num,size_t num);
分配和零初始化內(nèi)存塊
1.函數(shù)的功能是為num個大小為size的元素開辟空間。
2.與malloc的區(qū)別只在于calloc會在返回地址前將申請的空間的每個字母初始化為0。
#include <stdio.h> /* printf, scanf, NULL */ #include <stdlib.h> /* calloc, exit, free */ int main () { int i,n; int * pData; printf ("Amount of numbers to be entered: "); scanf ("%d",&i); pData = (int*) calloc (i,sizeof(int)); if (pData==NULL) exit (1); for (n=0;n<i;n++) { printf ("Enter number #%d: ",n+1); scanf ("%d",&pData[n]); } printf ("You have entered: "); for (n=0;n<i;n++) printf ("%d ",pData[n]); free (pData); return 0; }
四、realloc
void* realloc(void* ptr,size_t size);
重新分配內(nèi)存塊
1.ptr為要調(diào)整的內(nèi)存空間,size為調(diào)整后的新大小
2.返回值為調(diào)整后的內(nèi)存塊的起始位置
注意事項
1.若ptr指向的空間之后有足夠的空間可以追加,則直接追加,然后返回ptr。
2.若ptr指向的空間之后沒有足夠的內(nèi)存空間,則realloc函數(shù)會重新找一塊內(nèi)存空間,開辟一塊滿足需求的內(nèi)存空間,并且把原來內(nèi)存中的數(shù)據(jù)拷貝過來,釋放舊的內(nèi)存空間,最后返回新開辟的內(nèi)存空間的地址。
#include <stdio.h> /* printf, scanf, puts */ #include <stdlib.h> /* realloc, free, exit, NULL */ int main () { int input,n; int count = 0; int* numbers = NULL; int* more_numbers = NULL; do { printf ("Enter an integer value (0 to end): "); scanf ("%d", &input); count++; more_numbers = (int*) realloc (numbers, count * sizeof(int)); if (more_numbers!=NULL) { numbers=more_numbers; numbers[count-1]=input; } else { free (numbers); puts ("Error (re)allocating memory"); exit (1); } } while (input!=0); printf ("Numbers entered: "); for (n=0;n<count;n++) printf ("%d ",numbers[n]); free (numbers); return 0; }
五、常見的動態(tài)內(nèi)存分配錯誤
1.對NULL指針的解引用操作(要進行返回值的判斷)
2.對動態(tài)開辟空間的越界訪問
3.對非動態(tài)開辟內(nèi)存的空間的使用free進行釋放
4.使用free釋放一塊動態(tài)開辟內(nèi)存的一部分
(若指針位置發(fā)生變化,歸位后再進行釋放)
5.對同一塊動態(tài)內(nèi)存的多次釋放
6.動態(tài)開辟內(nèi)存忘記釋放(內(nèi)存泄漏)
六、柔性數(shù)組
C99中,結(jié)構(gòu)體中的最后一個元素是未知大小的數(shù)組,被稱為柔性數(shù)組成員。
特點
1.結(jié)構(gòu)體中柔性數(shù)組成員前必須至少有一個其他成員。
2.sizeof返回的這種結(jié)構(gòu)體的大小不包括柔性數(shù)組的內(nèi)存大小。
3.包含柔性數(shù)組成員的結(jié)構(gòu)體用malloc函數(shù)進行內(nèi)存動態(tài)內(nèi)存的動態(tài)分配,并且分配的內(nèi)存應(yīng)大于結(jié)構(gòu)體的大小,以適應(yīng)柔性數(shù)組的預(yù)期大小。
優(yōu)勢
1.方便內(nèi)存釋放。
2.利于訪問速度,減少內(nèi)存碎片。
#include<stdio.h> #include<stdlib.h> struct S { int n; int arr[]; }; int main() { struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int)); //給arr分配內(nèi)存20個字節(jié)的空間 if (ps == NULL) { return 1; } //……………………操作 free(ps); ps = NULL; return 0; }
到此這篇關(guān)于C語言深入講解動態(tài)內(nèi)存分配函數(shù)的使用的文章就介紹到這了,更多相關(guān)C語言動態(tài)內(nèi)存分配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言中結(jié)構(gòu)體的內(nèi)存對齊規(guī)則講解
C 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項,本篇讓我們來了解C 的結(jié)構(gòu)體內(nèi)存對齊2022-05-05深入分析C++中兩個大數(shù)相乘結(jié)果不正確的問題
本篇文章是對C++中兩個大數(shù)相乘結(jié)果不正確的問題進行了詳細的分析介紹,需要的朋友參考下2013-05-05