網站首頁 編程語言 正文
1 動態內存分配的介紹
- 手動分配空間手動釋放空間,根據自己的需要分配固定大小的內存空間。
- 動態內存分配在堆區分配的空間,堆區空間需要手動分配,手動釋放。
- 分配堆區的函數使用malloc函數,釋放堆區空間使用free函數。
- 如果堆區空間沒有手動釋放,當進程結束,系統會回收堆區的空間,一般都是手動釋放
2 malloc和free函數
#include <stdlib.h>
malloc函數 ----> 在堆區分配空間
void *malloc(size_t size);
功能:手動在堆區分配內存空間
參數:
@ size : 分配堆區空間的大小,以字節為單位
返回值:
成功:返回分配堆區空間的首地址
失?。悍祷豊ULLfree函數 ----> 釋放堆區的空間
void free(void *ptr);
功能:手動釋放堆區的空間
參數:
@ ptr : 釋放堆區空間的首地址
返回值:無
3 測試代碼
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
/*your code*/
#if 0
// 回顧:定義指針變量的初始化方式
int *p = NULL; // 指針變量p在棧區分配的空間
int a = 100; // 變量a在棧區分配的空間
p = &a; // 指針p指向棧區空間
char *str = "hello world";
// 指針變量str在棧區分配的空間
// "hello world" 在字符串的常量區
#endif
// 定義一個指針變量,指向一個堆區的空間
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指針指向的堆區空間進行初始化
*m_p = 1000;
printf("打印堆區空間中的值 : %d\n", *m_p);
#if 0
// 釋放堆區的空間
free(m_p);
// 將m_p指向NULL,防止野指針的出現
m_p = NULL;
#endif
// 為什么必須釋放完堆區空間指針讓指針指向NULL,如果不指向有可能會出現野指針
printf("釋放之前,m_p指針變量中存放的地址 = %p\n", m_p);
// 釋放堆區的空間,
// free函數只是單純的釋放了堆區的空間,別人就可以再次使用這塊堆區空間,
// free函數并沒有將m_p指針變量中存放的地址清空,因此需要成需要手動將m_p指向NULL
free(m_p);
printf("釋放之后,m_p指針變量中存放的地址 = %p\n", m_p);
// 釋放堆區空間沒有將m_p指向NULL,此時依然可以對m_p指向的空間賦值,
// 并且編譯不會報錯,也可以正常指向,但是這樣就訪問了非法的空間。
*m_p = 2000;
printf("打印釋放堆區空間之后m_p指向的空間的值 : %d\n", *m_p);
// 如果將m_p指向null之后,就可以預防野指針的出現,
// 當執行程序時就會報段錯誤
m_p = NULL;
*m_p = 3000;
printf("打印釋放堆區空間之后m_p指向的空間的值 : %d\n", *m_p);//段錯誤
return 0;
}
練習題:使用malloc在堆區給int *p; 分配(sizeof(int) * 10),大小的空間,通過終端輸入的方式對堆區進行初始化,然后使用冒泡排序的方式對堆區空間中的成員進行排序。使用多文件編程的方式實現。
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("請輸入要輸入元素的個數>");
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++){
//內層循環控制一趟排序
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個指針類型的變量,最終都指向一個堆區的空間
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指向的堆區空間釋放
goto ERR2;
}
c_p = (char *)malloc(sizeof(char));
if ( c_p == NULL)
{
printf("c_p malloc memory failed!\n");
// 如果失敗需要先將i_p和s_p指向的堆區空間釋放
goto ERR3;
}
// 如果都分配成功,不使用時手動釋放,
// 如果不手動釋放,當進行結束之后,系統也會進行回收。
free(c_p);
free(s_p);
free(i_p);
return 0;
ERR3:
free(s_p);
ERR2:
free(i_p);
ERR1:
return -1;
}
宏定義函數版:
#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個指針類型的變量,最終都指向一個堆區的空間
// 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指向的堆區空間釋放
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指向的堆區空間釋放
goto ERR3;
}
// 如果都分配成功,不使用時手動釋放,
// 如果不手動釋放,當進行結束之后,系統也會進行回收。
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個字節以參數c填入
參數:
? s:需要操作內存s的首地址
? c:填充的字符,c雖然參數為int,但必須是unsigned char , 范圍為0~255
? n:指定需要設置的大小
返回值:s的首地址
6 memcpy()
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
功能:拷貝src所指的內存內容的前n個字節到dest所值的內存地址上。
參數:
? dest:目的內存首地址
? src:源內存首地址,注意:dest和src所指的內存空間不可重疊,可能會導致程序報錯
? n:需要拷貝的字節數
返回值:dest的首地址
7 memcmp()
#include <string.h>
int memcmp(const void *s1, const void *s2, size_t n);
功能:比較s1和s2所指向內存區域的前n個字節
參數:
? s1:內存首地址1
? s2:內存首地址2
? n:需比較的前n個字節
返回值:
? 相等:=0
? 大于:>0
? 小于:<0
原文鏈接:https://distant-rove.blog.csdn.net/article/details/127583267
相關推薦
- 2022-12-02 Linux下的自動化構建工具之make/makefile的用法詳解_linux shell
- 2024-07-15 Spring Boot多環境指定yml或者properties
- 2024-07-18 【SpringBoot】SpringCache輕松啟用Redis緩存
- 2022-05-02 C/C++的各種字符串函數你知道幾個_C 語言
- 2023-03-20 C#字符集編碼的使用及說明_C#教程
- 2022-11-18 詳解SFTP命令_linux shell
- 2023-11-23 nginx偽靜態try_files命令解讀
- 2022-12-30 Golang反射獲取變量類型和值的方法詳解_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支