C語言動態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解
1 動態(tài)內(nèi)存分配的介紹
- 手動分配空間手動釋放空間,根據(jù)自己的需要分配固定大小的內(nèi)存空間。
- 動態(tài)內(nèi)存分配在堆區(qū)分配的空間,堆區(qū)空間需要手動分配,手動釋放。
- 分配堆區(qū)的函數(shù)使用malloc函數(shù),釋放堆區(qū)空間使用free函數(shù)。
- 如果堆區(qū)空間沒有手動釋放,當(dāng)進程結(jié)束,系統(tǒng)會回收堆區(qū)的空間,一般都是手動釋放
2 malloc和free函數(shù)
#include <stdlib.h>
malloc函數(shù) ----> 在堆區(qū)分配空間
void *malloc(size_t size);
功能:手動在堆區(qū)分配內(nèi)存空間
參數(shù):
@ size : 分配堆區(qū)空間的大小,以字節(jié)為單位
返回值:
成功:返回分配堆區(qū)空間的首地址
失?。悍祷豊ULLfree函數(shù) ----> 釋放堆區(qū)的空間
void free(void *ptr);
功能:手動釋放堆區(qū)的空間
參數(shù):
@ ptr : 釋放堆區(qū)空間的首地址
返回值:無
3 測試代碼
#include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]) { /*your code*/ #if 0 // 回顧:定義指針變量的初始化方式 int *p = NULL; // 指針變量p在棧區(qū)分配的空間 int a = 100; // 變量a在棧區(qū)分配的空間 p = &a; // 指針p指向棧區(qū)空間 char *str = "hello world"; // 指針變量str在棧區(qū)分配的空間 // "hello world" 在字符串的常量區(qū) #endif // 定義一個指針變量,指向一個堆區(qū)的空間 int *m_p = NULL; m_p = (int *)malloc(sizeof(int)); // 對返回值進行判斷 if(m_p == NULL) { printf("malloc memory failed!\n"); return -1; } printf("malloc memory successed!\n"); // 對m_p指針指向的堆區(qū)空間進行初始化 *m_p = 1000; printf("打印堆區(qū)空間中的值 : %d\n", *m_p); #if 0 // 釋放堆區(qū)的空間 free(m_p); // 將m_p指向NULL,防止野指針的出現(xiàn) m_p = NULL; #endif // 為什么必須釋放完堆區(qū)空間指針讓指針指向NULL,如果不指向有可能會出現(xiàn)野指針 printf("釋放之前,m_p指針變量中存放的地址 = %p\n", m_p); // 釋放堆區(qū)的空間, // free函數(shù)只是單純的釋放了堆區(qū)的空間,別人就可以再次使用這塊堆區(qū)空間, // free函數(shù)并沒有將m_p指針變量中存放的地址清空,因此需要成需要手動將m_p指向NULL free(m_p); printf("釋放之后,m_p指針變量中存放的地址 = %p\n", m_p); // 釋放堆區(qū)空間沒有將m_p指向NULL,此時依然可以對m_p指向的空間賦值, // 并且編譯不會報錯,也可以正常指向,但是這樣就訪問了非法的空間。 *m_p = 2000; printf("打印釋放堆區(qū)空間之后m_p指向的空間的值 : %d\n", *m_p); // 如果將m_p指向null之后,就可以預(yù)防野指針的出現(xiàn), // 當(dāng)執(zhí)行程序時就會報段錯誤 m_p = NULL; *m_p = 3000; printf("打印釋放堆區(qū)空間之后m_p指向的空間的值 : %d\n", *m_p);//段錯誤 return 0; }
練習(xí)題:使用malloc在堆區(qū)給int *p; 分配(sizeof(int) * 10),大小的空間,通過終端輸入的方式對堆區(qū)進行初始化,然后使用冒泡排序的方式對堆區(qū)空間中的成員進行排序。使用多文件編程的方式實現(xiàn)。
bubbling.h文件:
#ifndef __BUBBLING_H__ #define __BUBBLING_H__ #include <stdio.h> #include <stdlib.h> int *malloc_int(int len); void print(int *p,int len); void bubbling(int *p,int len); void free_p(int *p); #endif
main.c文件:
#include "bubbling.h" int main(int argc, const char *argv[]) { printf("請輸入要輸入元素的個數(shù)>"); int n=0; scanf("%d",&n); int *p=malloc_int(n); printf("請輸入要排序的元素>\n"); for(int i=0;i<n;i++){ scanf("%d",p+i); } printf("未排序前>\n"); print(p,n); bubbling(p,n); printf("排序后>\n"); print(p,n); free_p(p); p=NULL; return 0; }
malloc_free.c文件:
#include "bubbling.h" int *malloc_int(int len){ int *q=(int *)malloc(sizeof(int)*len); if(NULL==q){ printf("申請空間失敗!\n"); } return q; } void free_p(int *p){ if(NULL==p){ printf("傳參錯誤!\n"); } free(p); p=NULL; }
bubbling.c文件:
#include "bubbling.h" void bubbling(int *p,int len){ if(NULL==p){ printf("傳參錯誤!\n"); } for(int j = 0; j < len-1; j++){ //內(nèi)層循環(huán)控制一趟排序 for(int i = 0; i < len-1-j; i++){ //此處的 -1 是防止越界訪問的 //此處的 -j 是因為每趟都可以少比較一個元素 if(p[i] > p[i+1]){//如果是降序 只需要將此處的 > 改成 < 即可 //交換 int temp = p[i]; p[i] = p[i+1]; p[i+1] = temp; } } } }
print.c文件:
#include "bubbling.h" void print(int *p,int len){ if(NULL==p){ printf("傳參錯誤!\n"); } for(int i=0;i<len;i++){ printf("%4d",*(p+i)); } puts(""); }
4 goto的使用場合
常用于出錯處理
#include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]) { /*your code*/ // 1. 定義3個指針類型的變量,最終都指向一個堆區(qū)的空間 int *i_p = NULL; short *s_p = NULL; char *c_p = NULL; i_p = (int *)malloc(sizeof(int)); if ( i_p == NULL) { printf("i_p malloc memory failed!\n"); // 如果失敗直接退出,沒有問題 goto ERR1; } s_p = (short *)malloc(sizeof(short)); if ( s_p == NULL) { printf("s_p malloc memory failed!\n"); // 如果失敗需要先將i_p指向的堆區(qū)空間釋放 goto ERR2; } c_p = (char *)malloc(sizeof(char)); if ( c_p == NULL) { printf("c_p malloc memory failed!\n"); // 如果失敗需要先將i_p和s_p指向的堆區(qū)空間釋放 goto ERR3; } // 如果都分配成功,不使用時手動釋放, // 如果不手動釋放,當(dāng)進行結(jié)束之后,系統(tǒng)也會進行回收。 free(c_p); free(s_p); free(i_p); return 0; ERR3: free(s_p); ERR2: free(i_p); ERR1: return -1; }
宏定義函數(shù)版:
#include <stdio.h> #include <stdlib.h> #define NODE(T) T *T##_p = NULL; #define MALLOC(T) T##_p=(T *)malloc(sizeof(T)); int main(int argc, const char *argv[]) { /*your code*/ // 1. 定義3個指針類型的變量,最終都指向一個堆區(qū)的空間 // int *int_p = NULL; NODE(int) // short *s_p = NULL; NODE(short) // char *c_p = NULL; NODE(char) // i_p = (int *)malloc(sizeof(int)); MALLOC(int) if ( int_p == NULL) { printf("i_p malloc memory failed!\n"); // 如果失敗直接退出,沒有問題 goto ERR1; } // short_p = (short *)malloc(sizeof(short)); MALLOC(short) if ( short_p == NULL) { printf("s_p malloc memory failed!\n"); // 如果失敗需要先將i_p指向的堆區(qū)空間釋放 goto ERR2; } // char_p = (char *)malloc(sizeof(char)); MALLOC(char) if ( char_p == NULL) { printf("c_p malloc memory failed!\n"); // 如果失敗需要先將i_p和s_p指向的堆區(qū)空間釋放 goto ERR3; } // 如果都分配成功,不使用時手動釋放, // 如果不手動釋放,當(dāng)進行結(jié)束之后,系統(tǒng)也會進行回收。 free(char_p); free(short_p); free(int_p); return 0; ERR3: free(short_p); ERR2: free(int_p); ERR1: return -1; }
5 memset()
#include <string.h> void *memset(void *s, int c, size_t n);
功能:將s的內(nèi)存區(qū)域的前n個字節(jié)以參數(shù)c填入
參數(shù):
? s:需要操作內(nèi)存s的首地址
? c:填充的字符,c雖然參數(shù)為int,但必須是unsigned char , 范圍為0~255
? n:指定需要設(shè)置的大小
返回值:s的首地址
6 memcpy()
#include <string.h> void *memcpy(void *dest, const void *src, size_t n);
功能:拷貝src所指的內(nèi)存內(nèi)容的前n個字節(jié)到dest所值的內(nèi)存地址上。
參數(shù):
? dest:目的內(nèi)存首地址
? src:源內(nèi)存首地址,注意:dest和src所指的內(nèi)存空間不可重疊,可能會導(dǎo)致程序報錯
? n:需要拷貝的字節(jié)數(shù)
返回值:dest的首地址
7 memcmp()
#include <string.h> int memcmp(const void *s1, const void *s2, size_t n);
功能:比較s1和s2所指向內(nèi)存區(qū)域的前n個字節(jié)
參數(shù):
? s1:內(nèi)存首地址1
? s2:內(nèi)存首地址2
? n:需比較的前n個字節(jié)
返回值:
? 相等:=0
? 大于:>0
? 小于:<0
到此這篇關(guān)于C語言動態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解的文章就介紹到這了,更多相關(guān)C語言動態(tài)內(nèi)存分配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c語言實現(xiàn)足球比賽積分統(tǒng)計系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了c語言實現(xiàn)足球比賽積分統(tǒng)計系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05