最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c語言詳解動態(tài)內(nèi)存分配及常見錯誤的解決

 更新時間:2022年04月22日 14:32:36   作者:平凡的人1  
給數(shù)組分配多大的內(nèi)存空間?你是否和初學(xué)C時的我一樣,有過這樣的疑問。這一期就來聊一聊動態(tài)內(nèi)存的分配,讀完這篇文章,你可能對內(nèi)存的分配有一個更好的理解

為什么會有動態(tài)內(nèi)存分配

內(nèi)存使用方式有兩種

1.創(chuàng)建一個變量

2.創(chuàng)建一個數(shù)組

int a = 1;
int arr[10];

但是這兩種方式都有一些特點(diǎn)

1.空間是固定大小的,不會變

2.必須提前知道要開辟多少空間,必須指定數(shù)組的長度。

但是實(shí)際上,對于空間的需求,有些時候,我們并不知道要分配多少內(nèi)存空間,有時候需要在程序運(yùn)行時才知道,比如用一個數(shù)組存放班級學(xué)生的年齡,我們不知道有多少個學(xué)生,不知道需要多大的空間,而且編譯器又不支持變長的數(shù)組,應(yīng)該是常量表達(dá)式。這時候,用數(shù)組分配固定的空間就不適合了。

為了更好地分配內(nèi)存空間,這時候就需要我們的動態(tài)內(nèi)存分配了。

說到內(nèi)存,我們知道內(nèi)存分為3個區(qū)域,棧區(qū),堆區(qū),靜態(tài)區(qū)。

棧區(qū)——局部變量,函數(shù)形參

堆區(qū)——動態(tài)內(nèi)存分配

靜態(tài)區(qū)——全局變量,靜態(tài)變量(如static int a = 10)

動態(tài)內(nèi)存函數(shù)的介紹

malloc

void *malloc( size_t size );

函數(shù)向堆區(qū)開辟一塊連續(xù)的空間,返回空間的起始地址。

  • 開辟成功,返回一個開辟好的空間的指針
  • 開辟失敗,返回NULL指針,所以要檢查是否開辟成功
  • 返回的類型是void*,所以malloc并不知道開辟的類型,自己決定
  • 如果size為0,malloc的行為是標(biāo)準(zhǔn)未定義的,取決于編譯器
  • 記得引用頭文件#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
    int* p = (int*)malloc(10 * sizeof(int));
    if (p == NULL)
    {
        //打印錯誤原因的一個方式
        printf("%s\n", strerror(errno));
    }
    else
    {
        //正常使用
        int i = 0;
        for (i = 0; i < 10; i++)
        {
            *(p + i) = i;
        }
        for (i = 0; i < 10; i++)
        {
            printf("%d ", *(p+i));
        }
    }
    //釋放
    free(p);
    p = NULL;
    return 0;
}

 free

void free( void *memblock );

c語言提供一個函數(shù)free,專門用來動態(tài)內(nèi)存的回收和釋放的 

頭文件是#include <stdlib.h>

注意幾點(diǎn):

用于動態(tài)開辟的內(nèi)存,如果不是的話,那free函數(shù)行為是未定義的

如果指針是NULL指針,則函數(shù)什么事都不做

被free后的指針最好手動置為NULL,避免野指針,造成錯誤

free(p);
p=NULL;

calloc

void *calloc( size_t num, size_t size );

calloc也是用來動態(tài)開辟空間。頭文件也為#include <stdlib.h>

與malloc的區(qū)別:

參數(shù)不同

與malloc的區(qū)別只在于calloc會返回地址之前把申請的空間的每個字節(jié)初始化為0。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
    //malloc(10*sizeof(int));
    int*p = (int*)calloc(10, sizeof(int));
    if (p == NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 10; i++)
        {
            printf("%d ", *(p + i));
        }
    }
    free(p);
    p = NULL;
    return 0;
}

 調(diào)試一下,可以看到內(nèi)存都初始化為0了

根據(jù)實(shí)際情況,如果需要初始化的話那就使用calloc

realloc

void *realloc( void *ptr, size_t size );

頭文件也是引用#include <stdlib.h>

ptr是要調(diào)整的內(nèi)存地址

size調(diào)整之后新大小,而不是增加的大小

返回值為調(diào)整之后的內(nèi)存起始位置

realloc函數(shù)的出現(xiàn)讓動態(tài)內(nèi)存管理更加靈活

有時候我們發(fā)現(xiàn)申請的空間太小,有時候又會覺得申請過大了,為了合理的分配內(nèi)存,我們可以對內(nèi)存的大小做靈活的調(diào)整,realloc可以做到對動態(tài)內(nèi)存大小的調(diào)整

注意事項(xiàng)

realloc在調(diào)整內(nèi)存存在兩種情況

情況1:原有空間之后有足夠大的空間

  • 如果p指向的空間之后有足夠的內(nèi)存可以追加,則直接追加,后返回p

情況2:原有空間之后沒有足夠的空間

  • 如果p指向的空間之后沒有足夠的內(nèi)存空間可以追加,則realloc函數(shù)會重新找一個新的內(nèi)存區(qū)域開辟一塊滿足需求的空間,并且把原來內(nèi)存中的數(shù)據(jù)拷貝回來,釋放舊的內(nèi)存空間,最后返回新開辟的內(nèi)存空間地址
  • 得用一個新的變量來接收realloc的返回值

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
    int* p = (int*)malloc(20);
    if (p == NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 5; i++)
        {
            *(p + i) = i;
        }
    }
    //在使用malloc開辟的20個空間
    //假設(shè)這里20個字節(jié)不能滿足我們的使用
    //希望我們能有40個字節(jié)的空間
    //這里就可以使用realloc來調(diào)整動態(tài)開辟的內(nèi)存
    int* ptr = realloc(p, 40);
    if (ptr != NULL)
    {
        p = ptr; 
        int i = 0;
        for (i = 5; i < 10; i++)
        {
            *(p + i) = i;
        }
        for (i = 0; i < 10; i++)
        {
            printf("%d ", *(p+ i));
        }
    }
    free(p);
    p = NULL;
    return 0;
}

常見的錯誤

對NULL指針的解引用操作

int main()
{
    int* p = (int*)malloc(INT_MAX/4);
    *p = 20;//如果p是空指針,就會有問題;
    free(p);
    return 0;
}

越界訪問

int* p = (int*)malloc(40);
    if (p == NULL)
    {
        return 0;
    }
    int i = 0;
    //越界
    for (i = 0; i <= 10; i++)
    {
        *(p + i) = i;
    }
    free(p);
    p = NULL;

應(yīng)該是i<10

對非動態(tài)內(nèi)存進(jìn)行free

 int a = 10;
    int* p = &a;
    free(p);
    p = NULL;

使用free釋放動態(tài)開辟內(nèi)存的一部分

int* p = (int*)malloc(40);
    if (p == NULL)
    {
        return 0;
    }
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        *p++ = i;
    }
    free(p);
    return 0;

 p不在指向動態(tài)內(nèi)存開辟的起始位置,我們應(yīng)該重新定義一個指針來記住起始地址

對同一塊動態(tài)內(nèi)存多次釋放

int* p = (int*)malloc(40);
    if (p == NULL)
    {
        return 0;
    }
    free(p);
    free(p);

對動態(tài)內(nèi)存內(nèi)存忘記釋放(內(nèi)存泄漏)

忘記釋放動態(tài)開辟的內(nèi)存,就會造成內(nèi)存泄漏

 while (1)
    {
        malloc(1);
        Sleep(1000);
    }

申請內(nèi)存而不還,計算機(jī)的內(nèi)存是有限的,內(nèi)存將會被耗干

到此這篇關(guān)于c語言詳解動態(tài)內(nèi)存分配及常見錯誤的解決的文章就介紹到這了,更多相關(guān)c語言動態(tài)內(nèi)存分配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Objective-C不帶加減號的方法實(shí)例

    Objective-C不帶加減號的方法實(shí)例

    顯而易見的事實(shí)是,Objective-C 中,+ 表示類方法,- 表示實(shí)例方法,這篇文章主要給大家介紹了關(guān)于Objective-C不帶加減號的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • c語言隨機(jī)數(shù)函數(shù)示例

    c語言隨機(jī)數(shù)函數(shù)示例

    這篇文章主要介紹了c語言隨機(jī)數(shù)函數(shù)示例,需要的朋友可以參考下
    2014-04-04
  • C++使用boost::lexical_cast進(jìn)行數(shù)值轉(zhuǎn)換

    C++使用boost::lexical_cast進(jìn)行數(shù)值轉(zhuǎn)換

    這篇文章介紹了C++使用boost::lexical_cast進(jìn)行數(shù)值轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 基于C語言實(shí)現(xiàn)的掃雷游戲代碼

    基于C語言實(shí)現(xiàn)的掃雷游戲代碼

    這篇文章主要介紹了基于C語言實(shí)現(xiàn)的掃雷游戲代碼,對于學(xué)習(xí)游戲開發(fā)的朋友有一定的借鑒價值,需要的朋友可以參考下
    2014-08-08
  • C語言詳解實(shí)現(xiàn)字符菱形的方法

    C語言詳解實(shí)現(xiàn)字符菱形的方法

    字符菱形是指給定一個字符,用它構(gòu)造一個對角線長5個字符,傾斜放置的菱形。輸入輸入只有一行, 包含一個字符。輸出該字符構(gòu)成的菱形
    2022-04-04
  • C++實(shí)現(xiàn)猜數(shù)字小游戲

    C++實(shí)現(xiàn)猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • c語言常量定義規(guī)則知識點(diǎn)總結(jié)

    c語言常量定義規(guī)則知識點(diǎn)總結(jié)

    在本篇文章里小編給大家整理的是關(guān)于c語言常量定義規(guī)則知識點(diǎn)總結(jié),需要的朋友們可以學(xué)習(xí)下。
    2020-03-03
  • C語言庫函數(shù)中qsort()的用法

    C語言庫函數(shù)中qsort()的用法

    大家好,本篇文章主要講的是C語言庫函數(shù)中qsort()的用法,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C++?左值引用與一級指針示例詳解

    C++?左值引用與一級指針示例詳解

    這篇文章主要介紹了C++?左值引用與一級指針,本文給大家介紹了C++?(左值)引用和指針簡介,結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制

    使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制

    這篇文章主要介紹了使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04

最新評論

肃宁县| 万全县| 壶关县| 县级市| 蒙阴县| 武隆县| 泸定县| 盈江县| 正宁县| 尼玛县| 周至县| 榆社县| 南开区| 易门县| 宽城| 都兰县| 尼玛县| 涪陵区| 莱阳市| 双辽市| 高清| 丹寨县| 海门市| 澜沧| 湖南省| 桦南县| 保德县| 黄大仙区| 阿合奇县| 体育| 简阳市| 依安县| 红河县| 韶关市| 扎赉特旗| 淳化县| 罗山县| 民勤县| 渑池县| 奎屯市| 上虞市|