日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C語言動態內存分配和內存操作函數使用詳解_C 語言

作者:編程遠泊 ? 更新時間: 2023-02-02 編程語言

1 動態內存分配的介紹

  • 手動分配空間手動釋放空間,根據自己的需要分配固定大小的內存空間。
  • 動態內存分配在堆區分配的空間,堆區空間需要手動分配,手動釋放。
  • 分配堆區的函數使用malloc函數,釋放堆區空間使用free函數。
  • 如果堆區空間沒有手動釋放,當進程結束,系統會回收堆區的空間,一般都是手動釋放

2 malloc和free函數

#include <stdlib.h>

malloc函數 ----> 在堆區分配空間
void *malloc(size_t size);
功能:手動在堆區分配內存空間
參數:
@ size : 分配堆區空間的大小,以字節為單位
返回值:
成功:返回分配堆區空間的首地址
失?。悍祷豊ULL

free函數 ----> 釋放堆區的空間
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

欄目分類
最近更新