指针的动态初始化malloc与销毁free
指針動態初始化:
int *p = (int*)malloc(sizeof(int)*3);//初始化為指向3個元素的數組
if(!p) exit -1;//這個地方一定要進行判斷,因為若動態初始化不成功,在使用p[0]、p[1]、p[2]時報錯。
指針的銷毀:
free(p);
p = NULL;//避免p為野指針,需要賦值為NULL
? ? ? ? ?//p中的值仍為原先的內存地址,此時要進行賦值NULL。
? ? ? ? ?//釋放內存后,賦值為NULL的好處還有:當p為NULL時,即便再free n次也不會出錯!!!
注意:free的含義:free之后,是將由malloc分配的內存交還給系統支配,而代碼支配不了了,即由malloc分配的內存中內容由系統進行處理。
其中存在兩個值:一個是指針的值,指針的值并未發生改變,還是原先指向malloc分配的地址。
另一個是malloc分配的內存值,這其中的值取決于系統有沒有使用該內存,如果使用了,該內存中的值會發生改變,如果沒有使用,則還是保持原先的值。
總結:
初始化要判斷內存是否申請成功;
銷毀時要賦值NULL?。
//************************
1、變量內存的動態分配(創建)與釋放:通過指針,動態間接賦值、取值
指針變量名=new?數據類型(初始值);?初始值可省略,后邊再賦值。
delete?指針變量名;
#include<iostream> using namespace std; int main() {//int *p = new int; *p = 5;int *p = new int(5);//new運算符,動態創建一個int型變量(無變量名),值為5。cout << *p;//輸出所指地址的值delete p;//釋放指針變量的內存空間return 0; }2、一維數組的動態分配(創建)與釋放:
指針變量名=new?數據類型[正整數常量、變量或表達式];
delete [ ]指針變量名;
#include<iostream> using namespace std; int main() {int *p = new int[5];//new運算符,動態創建一個int型數組(無數組名)。*(p + 1) = 10;//賦值第2個元素//或p[1]=10;cout << p[1];//輸出所指地址的值delete []p;//釋放指針變量數組的內存空間return 0; }顯示Fibonacci數列的前N項,0,1,1,2,3,5,8,…
#include<iostream> using namespace std; int main() {int N;cin >> N;int *p = new int[N]; //動態創建包含N個元素的數組p[0] = 0; p[1] = 1;//給定第1、2元素的值,等效*p=0;*(p+1)=1;for (int i = 2; i < N; i++){p[i] = p[i - 1] + p[i - 2];}for (int i = 0; i < N; i++){cout << p[i] << " ";}delete []p;//釋放指針變量數組的內存空間return 0; }//************************
什么是動態內存的申請和釋放? 當程序運行到需要一個動態變量時,需要向系統的堆中申請一塊內存,用來存儲這塊變量,這就是內存的申請。當程序不需要這個變量時,就需要把申請的這塊內存釋放掉,這就是內存的釋放。往往內存的申請和釋放是一起使用的,只要有內存的申請,就要有內存的釋放,避免出現內存泄漏。 C語言指針的申請: (1).在C語言中使用malloc函數申請內存,函數原形:?void* malloc(size_t size); 參數size代表申請的內存的字節數,參數size_t代表指針的類型,比如int char或者是結構體的類型。如果內 存申請成功返回內存的首地址,如果申請失敗,返回NULL(注意NULL全部大寫) (2).在使用該函數的過程中,需要注意以下幾點: 1.該函數的參數很簡單,只是申請內存的大小,單位是字節 2.申請內存后,必須要檢查是否內存分配成功。 3.申請到的內存是一塊連續的內存,該函數和free()函數配對使用。 4.雖然該函數的類型是(void*),但是在使用時還是建議進行強制類型轉換 (3).內存申請的例子: char *P = NULL;(給指針初始化,防止出現野指針) P = (char *)malloc(10 * sizeof(char));?? if(P == NULL){ exit(1); }else{ gets(P); } C語言指針的釋放: (1).在C語言中使用free函數釋放內存,函數原形:void free(void *ptr); 參數ptr代表內存的首地址,該函數沒有返回值。 (2).在使用該函數的過程中,需要注意以下幾點: 1.該函數釋放的是指針指向的內存,釋放的是內存,不是指針。釋放內存后指針要指向NULL 2.和malloc函數配對使用,內存申請后要記得釋放,避免內存泄漏。 3.不允許重復釋放。 (3).內存釋放的例子: if(P != NULL){ free(P); P = NULL; //指針釋放之后并不為空,要設置其為空。 } 注意: 1.free()函數只能釋放堆空間,堆是大家共有的空間,分局部堆和全局堆,全局堆是沒有分配的空間,局部堆是用戶分配的空間。用過堆的內存之后要記得還給系統,不然容易發生內存泄漏。 2.棧是線程獨有的,每個線程的棧都是互相獨立的,每個函數都有自己的棧,棧被用來在函數之間傳遞參數。像代碼區,靜態變量,全局變量,棧區上的變量都是不需要程序員進行釋放的。(這些區域上的空間,不能用free()函數釋放) 3.野指針:野指針指的是指向“垃圾”內存的指針,不是NULL指針。出現野指針主要有以下幾個原因: ①.指針沒有初始化(指針如果沒有初始化,值是不確定的。也就是說,沒有初始化的指針,指向的是垃圾內存,非常危險。) ②.指針free之后,沒有設置為NULL。 ③.指針超越了變量的作用范圍。指針操作時由于邏輯上的疏忽,導致指針訪問了非法內存,這種情況是非常容易出現的。 ④.不要返回指向棧內存的指針。 //***************************主要初步介紹malloc、free、calloc、realloc的基本。日后會有更詳細的內容。
malloc、free分別用于動態內存分配和釋放。
malloc會從內存池里提取一塊合適的內存(連續的),并返回指向這塊內存(起始位置的指針,該指針的類型為void*指針(因為malloc不知道你請求的內存需要存儲的數據類型),而且這塊內存并沒有初始化。
如果操作系統無法提供給malloc足夠的內存,malloc就會返回一個NULL指針。因此必須對每個從malloc返回的指針進行檢查。
?1?#include?<stdio.h>
?2?#include?<stdlib.h>
?3?
?4?int?main()?
?5?{
?6?????int?*pi;
?7?????int?i;
?8?????pi?=?malloc(25?*?sizeof(?int?));
?9?????
10?????if(?pi?==?NULL?)
11?????{
12?????printf(?"Out?of?memory!\n"?);
13?????exit(1);
14?????}
15?????
16?????for(i?=?0;?i?!=?25;?i++)
17?????????pi[i]?=?i;
18?
19?????for(i?=?0;?i?!=?25;?i++)
20?????????printf("%d?",?pi[i]);
21?????printf("\n");
22?
23?????return?0;
24?}?
?
calloc也可以用于內存分配,但是返回指向內存的指針之前會初始化為0。而且calloc和malloc請求內存數量的方式也不一樣。
realloc用于修改一個原先已經分配的內存大小。PS:若原來的內存塊無法改變大小,realloc將分配另一塊正確的小的內存,并把原來的那塊內存的內容復制到新的內存塊。
free函數的參數為一個先前從malloc、calloc、realloc返回的值。對NULL指針不會產生任何效果。
?
動態內存分配最常見的錯誤是忘記檢查請求的內存是否分配成功。
《C與指針》里面提供了一個程序可以減少錯誤的內存分配器。
代碼如下:
1?#include?<stdlib.h>
2?
3?#define?malloc??//用于防止由于其他代碼塊直接塞入程序而導致偶爾直接調用malloc
4?#define?MALLOC(num,?type)?(type?*)alloc((num)?*?sizeof(type))//接受元素的數目和類型,調用alloc函數獲得內存,alloc調用malloc并進行檢查,確保返回的指針不是NULL
5?extern?void?*alloc(?size_t?size?);?
?1?#include?<stdio.h>
?2?#include?"alloc.h"
?3?#undef?malloc
?4?
?5?void?*alloc(?size_t?size?)
?6?{
?7?????void?*new_mem;
?8?????/*
?9??????*?請求所需的內存,并檢查是否分配成功
10??????*/
11?????new_mem?=?malloc(?size?);
12?????if(?new_mem?==?NULL?)
13?????{
14?????????printf("Out?of?memory!\n"?);
15?????????exit(1);
16?????}
17?????return?new_mem;
18?}?
??1?#include?<stdio.h>
?2?#include?"alloc.h"
?3?
?4?int?main()
?5?{
?6?????int?*new_memory;
?7?????int?i;
?8?
?9?????/*
10??????*?獲得一個整型數組
11??????*/
12?????new_memory?=?MALLOC(?25,?int?);
13?????
14?????for(i?=?0;?i?!=?25;?i++)
15?????????new_memory[i]?=?i;
16?
17?????for(i?=?0;?i?!=?25;?i++)
18?????????printf("%d?",?new_memory[i]);
19?????printf("\n");
20?????return?0;
21?}
//***************************
關于malloc申請內存的函數
一、定義
malloc函數是一種分配長度為num_bytes字節的內存塊的函數,可以向系統申請分配指定size個字節的內存空間。malloc的全稱是memory allocation,中文叫動態內存分配,
函數返回的類型是void*類型。void*表示未確定的類型。
C,C++規定,void* 類型可以通過類型轉換強制轉換為任何其它類型的指針。
二、函數聲明與使用
頭文件
#include <stdlib.h>
或者
#include <malloc.h>
void *malloc(size_t size);
備注:void* 表示未確定類型的指針,void *可以指向任何類型的數據,更明確的說是指申請內存空間時還不知道用戶是用這段空間來存儲什么類型的數據(比如是char還是int或者其他數據類型)。
三、與new的區別
1)從本質上來說,malloc(Linux上具體實現可以參考man malloc,glibc通過brk()&mmap()實現)是libc里面實現的一個函數,如果在source code中沒有直接或者間接include過stdlib.h,那么gcc就會報出error:‘malloc’ was not declared in this scope。如果生成了目標文件(假定動態鏈接malloc),如果運行平臺上沒有libc(Linux平臺,手動指定LD_LIBRARY_PATH到一個空目錄即可),或者libc中沒有malloc函數,那么會在運行時(Run-time)出錯。new則不然,是c++的關鍵字,它本身不是函數。new不依賴于頭文件,c++編譯器就可以把new編譯成目標代碼(g++4.6.3會向目標中插入_Znwm這個函數,另外,編譯器還會根據參數的類型,插入相應的構造函數)。
2)在使用上來說
???
???1、new 返回指定類型的指針,并且可以自動計算所需要大小?
int *p;
p = new int;//返回類型為int *類型(整數型指針),分配大小為sizeof(int);
???
而 malloc 則必須要由我們計算字節數,并且在返回后強行轉換為實際類型的指針。
int *p;
p = (int*)malloc(sizeof(int) * 128);//分配128個(可根據實際需要替換該數值)整型存儲單元,//并將這128個連續的整型存儲單元的首地址存儲到指針變量p中
double *pd = (double*)malloc(sizeof(double) * 12);//分配12個double型存儲單元,//并將首地址存儲到指針變量pd中
??2、另外有一點不能直接看出的區別是,malloc 只管分配內存,并不能對所得的內存進行初始化,所以得到的一片新內存中,其值將是隨機的。所以malloc的內存要首先進行初始化
?
總結
以上是生活随笔為你收集整理的指针的动态初始化malloc与销毁free的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超简单:解析 yml 类型(applic
- 下一篇: docker 虚悬镜像 ( 悬空镜像 )