C語言動(dòng)態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解
1 動(dòng)態(tài)內(nèi)存分配的介紹
- 手動(dòng)分配空間手動(dòng)釋放空間,根據(jù)自己的需要分配固定大小的內(nèi)存空間。
- 動(dòng)態(tài)內(nèi)存分配在堆區(qū)分配的空間,堆區(qū)空間需要手動(dòng)分配,手動(dòng)釋放。
- 分配堆區(qū)的函數(shù)使用malloc函數(shù),釋放堆區(qū)空間使用free函數(shù)。
- 如果堆區(qū)空間沒有手動(dòng)釋放,當(dāng)進(jìn)程結(jié)束,系統(tǒng)會(huì)回收堆區(qū)的空間,一般都是手動(dòng)釋放
2 malloc和free函數(shù)
#include <stdlib.h>
malloc函數(shù) ----> 在堆區(qū)分配空間
void *malloc(size_t size);
功能:手動(dòng)在堆區(qū)分配內(nèi)存空間
參數(shù):
@ size : 分配堆區(qū)空間的大小,以字節(jié)為單位
返回值:
成功:返回分配堆區(qū)空間的首地址
失敗:返回NULLfree函數(shù) ----> 釋放堆區(qū)的空間
void free(void *ptr);
功能:手動(dòng)釋放堆區(qū)的空間
參數(shù):
@ ptr : 釋放堆區(qū)空間的首地址
返回值:無
3 測(cè)試代碼
#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
// 定義一個(gè)指針變量,指向一個(gè)堆區(qū)的空間
int *m_p = NULL;
m_p = (int *)malloc(sizeof(int));
// 對(duì)返回值進(jìn)行判斷
if(m_p == NULL) {
printf("malloc memory failed!\n");
return -1;
}
printf("malloc memory successed!\n");
// 對(duì)m_p指針指向的堆區(qū)空間進(jìn)行初始化
*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,如果不指向有可能會(huì)出現(xiàn)野指針
printf("釋放之前,m_p指針變量中存放的地址 = %p\n", m_p);
// 釋放堆區(qū)的空間,
// free函數(shù)只是單純的釋放了堆區(qū)的空間,別人就可以再次使用這塊堆區(qū)空間,
// free函數(shù)并沒有將m_p指針變量中存放的地址清空,因此需要成需要手動(dòng)將m_p指向NULL
free(m_p);
printf("釋放之后,m_p指針變量中存放的地址 = %p\n", m_p);
// 釋放堆區(qū)空間沒有將m_p指向NULL,此時(shí)依然可以對(duì)m_p指向的空間賦值,
// 并且編譯不會(huì)報(bào)錯(cuò),也可以正常指向,但是這樣就訪問了非法的空間。
*m_p = 2000;
printf("打印釋放堆區(qū)空間之后m_p指向的空間的值 : %d\n", *m_p);
// 如果將m_p指向null之后,就可以預(yù)防野指針的出現(xiàn),
// 當(dāng)執(zhí)行程序時(shí)就會(huì)報(bào)段錯(cuò)誤
m_p = NULL;
*m_p = 3000;
printf("打印釋放堆區(qū)空間之后m_p指向的空間的值 : %d\n", *m_p);//段錯(cuò)誤
return 0;
}練習(xí)題:使用malloc在堆區(qū)給int *p; 分配(sizeof(int) * 10),大小的空間,通過終端輸入的方式對(duì)堆區(qū)進(jìn)行初始化,然后使用冒泡排序的方式對(duì)堆區(qū)空間中的成員進(jìn)行排序。使用多文件編程的方式實(shí)現(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("請(qǐng)輸入要輸入元素的個(gè)數(shù)>");
int n=0;
scanf("%d",&n);
int *p=malloc_int(n);
printf("請(qǐng)輸入要排序的元素>\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("申請(qǐng)空間失敗!\n");
}
return q;
}
void free_p(int *p){
if(NULL==p){
printf("傳參錯(cuò)誤!\n");
}
free(p);
p=NULL;
}
bubbling.c文件:
#include "bubbling.h"
void bubbling(int *p,int len){
if(NULL==p){
printf("傳參錯(cuò)誤!\n");
}
for(int j = 0; j < len-1; j++){
//內(nèi)層循環(huán)控制一趟排序
for(int i = 0; i < len-1-j; i++){
//此處的 -1 是防止越界訪問的
//此處的 -j 是因?yàn)槊刻硕伎梢陨俦容^一個(gè)元素
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("傳參錯(cuò)誤!\n");
}
for(int i=0;i<len;i++){
printf("%4d",*(p+i));
}
puts("");
}
4 goto的使用場(chǎng)合
常用于出錯(cuò)處理
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
/*your code*/
// 1. 定義3個(gè)指針類型的變量,最終都指向一個(gè)堆區(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;
}
// 如果都分配成功,不使用時(shí)手動(dòng)釋放,
// 如果不手動(dòng)釋放,當(dāng)進(jìn)行結(jié)束之后,系統(tǒng)也會(huì)進(jìn)行回收。
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個(gè)指針類型的變量,最終都指向一個(gè)堆區(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;
}
// 如果都分配成功,不使用時(shí)手動(dòng)釋放,
// 如果不手動(dòng)釋放,當(dāng)進(jìn)行結(jié)束之后,系統(tǒng)也會(huì)進(jìn)行回收。
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個(gè)字節(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個(gè)字節(jié)到dest所值的內(nèi)存地址上。
參數(shù):
? dest:目的內(nèi)存首地址
? src:源內(nèi)存首地址,注意:dest和src所指的內(nèi)存空間不可重疊,可能會(huì)導(dǎo)致程序報(bào)錯(cuò)
? 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個(gè)字節(jié)
參數(shù):
? s1:內(nèi)存首地址1
? s2:內(nèi)存首地址2
? n:需比較的前n個(gè)字節(jié)
返回值:
? 相等:=0
? 大于:>0
? 小于:<0
到此這篇關(guān)于C語言動(dòng)態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解的文章就介紹到這了,更多相關(guān)C語言動(dòng)態(tài)內(nèi)存分配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C語言動(dòng)態(tài)內(nèi)存分配圖文講解
- 詳解C語言中的動(dòng)態(tài)內(nèi)存管理
- 一文帶你搞懂C語言動(dòng)態(tài)內(nèi)存管理
- C語言動(dòng)態(tài)內(nèi)存管理malloc柔性數(shù)組示例詳解
- C語言動(dòng)態(tài)內(nèi)存的分配最全面分析
- 詳解C語言中動(dòng)態(tài)內(nèi)存管理及柔性數(shù)組的使用
- 深入了解C語言的動(dòng)態(tài)內(nèi)存管理
- C語言sizeof與字符串處理與動(dòng)態(tài)內(nèi)存分配及main函數(shù)參數(shù)詳解
- Js逆向教程作用域和自執(zhí)行函數(shù)介紹
相關(guān)文章
OpenCV邊緣提取算法流程的實(shí)現(xiàn)(附DEMO)
本文主要介紹了OpenCV邊緣提取算法流程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
在c和c++中實(shí)現(xiàn)函數(shù)回調(diào)
如何在c和c++中實(shí)現(xiàn)函數(shù)回調(diào)呢?現(xiàn)在小編就和大家分享一下在c/c++中實(shí)現(xiàn)函數(shù)回調(diào)的示例代碼,需要的朋友可以參考下2013-07-07
C++實(shí)現(xiàn)LeetCode(77.Combinations 組合項(xiàng))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(Combinations 組合項(xiàng)),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07

