網(wǎng)站首頁 編程語言 正文
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 測試代碼
#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));
// 對返回值進(jìn)行判斷
if(m_p == NULL) {
printf("malloc memory failed!\n");
return -1;
}
printf("malloc memory successed!\n");
// 對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í)依然可以對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),大小的空間,通過終端輸入的方式對堆區(qū)進(jìn)行初始化,然后使用冒泡排序的方式對堆區(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("請輸入要輸入元素的個(gè)數(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("傳參錯(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的使用場合
常用于出錯(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
原文鏈接:https://distant-rove.blog.csdn.net/article/details/127583267
相關(guān)推薦
- 2023-07-26 webpack中plugin的工作原理
- 2022-08-10 C++學(xué)習(xí)之多態(tài)的使用詳解_C 語言
- 2022-06-26 深入解析python返回函數(shù)和匿名函數(shù)_python
- 2022-09-20 react-redux?action傳參及多個(gè)state處理的實(shí)現(xiàn)_React
- 2023-02-17 Python去除字符串前后空格的三種方法匯總_python
- 2022-08-05 詳解C#通過反射獲取對象的幾種方式比較_C#教程
- 2022-09-15 python安裝whl文件的實(shí)戰(zhàn)步驟_python
- 2023-01-15 C#實(shí)現(xiàn)虛擬鍵盤的實(shí)例詳解_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支