程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言----內存區劃分

C語言----內存區劃分

編輯:關於C語言

C語言----內存區劃分


一、棧區、堆區、靜態區(全局區)、常量區、代碼區:

1、棧:由系統根據數據類型所占字節數在此區域開辟存儲空間,使用結束後,再由系統釋放。
(系統分配,系統釋放)

2、堆、手動分配,手動釋放。

3、靜態、 static:直到程序運行結束 才會被 釋放。

4、常量占用內存,只讀狀態,決不可修改。

5、代碼、所有的語句編譯後會生成CPU指令存儲在代碼區。

二、malloc、calloc、realloc 函數的使用:

1、void * mallloc ( unsigned size ) ;

2、void * calloc ( unsigned int n , unsigned size ) ;
n 個 size 空間( n * size ),分配後會對整個 空間 清零。

3、void * realloc ( void *p , unsigned newSize ) ;
按給定的地址以及給定的大小重新分配

三、內存操作函數:

1、 void * memset ( void *s , int c , size_t n ) ;
從 s 指向的內存開始拷貝到 dest,

2、void * memcpy ( void * dest , const void * source , size_t n ) ;
從 source 指向的內存開始拷貝到 dest ,拷貝 n 個 字節

3、int memcmp( const void * buf1 , const void * buf2 , unsigned int count ) ;
比較 buf 1 和 buf 2 指向的內存是否相同, 比較 count 個 字節
大於零、等於零、小於零

例題:

//
//  main.m
//  C_Project_10
//
//  Created by  on 15/3/25.
//  Copyright (c) 2015年 . All rights reserved.
//

#import 


void word()
{
    char *words[3] = {0};
    int i = 0 ;
    while( i < 3)
    {
        words[i] = (char *)malloc( INT32_MAX );
        i++;
    }
    printf( "請輸入三個字符串:\n" );
    for( int i = 0; i < 3; i++ )
        scanf( "%s", words[i] );

    for( int i = 0; i < 3; i++ )
    {
        printf( "address:%p->content:%s\n", words[i], words[i] );
        free( words[i] );// 注意 釋放 誰?
        words[i] = NULL;
    }
}


void  callocAndRealloc()
{
    //calloc 函數是分配 n 個 size 字節的空間,並對開辟的對內存空間按字節清零操作
    int *p = calloc( 4, sizeof( int ) );
    for( int i = 0; i < 4; i++ )
        printf( "%d\t", *(p + i) );
    printf( "\n" );
    //realloc 函數擁有兩個功能:
    //1、根據給定的已有空間的首地址來判斷該空間後續是否有足夠大得可用空間,如果存在,則順序追加 newSize -- 原有大小的字節數;
    //2、如果沒有可用空間,則在堆區中其他空間尋找 newSize 大小的空間 開辟,並將原來空間的數據拷貝過去,同時釋放掉原來空間的內存;
    //3、這也是 realloc 返回的地址有時跟傳入 的地址相同,有時不同的原因。
    int *q = realloc( p, 10000 );
    printf( "%p\n", p );
    printf( "%p\n", q );
    //memset 函數是對指定的堆內存空間做初始化操作的函數,其參數列表為(void *p, int c, int size );表示 p 所指向的空間中 size 個字節被初始化為 c 。
    // 注意是把 每個 字節 初始化成 整數 c 。
    q = memset( q, 1, 2000 );
    for ( int i = 0; i < 500; i++ )
        printf( "內存初始化:%d", *(q + i));

    free( p );
    p = NULL;
    free( q );
    q = NULL;

}


void memsetAndMemcpy()
{
    int *p = malloc( sizeof( int ) * 4 );
    for ( int i = 0; i < 4; i++ )
    {
        *(p + i) = arc4random() % 21 + 10;
        printf( "%d\t", *(p + i) );
    }
    printf( "\n" );
    int *q = malloc( sizeof( int ) * 4 );
    //將函數參數列表中第二個指針指向的堆內存空間中的指定的 n 個字節拷貝到第一個指針指向的內存空間的對應位置,實現內存拷貝的過程。
    memcpy( q, p, sizeof( int ) * 4 );
    for ( int i = 0; i < 4; i++ )
    {
        printf( "%d\t", *(q + i) );
    }

    *q = 9;
    // memcmp 函數是將兩個指針指向的堆內存空間的指定字節數,按字節做差值,如果最終結果為 0 , 代表被比較的空間內容相同,否則表示不同。
    int result = memcmp( p, q, sizeof( int ) * 4 );
    printf( "\n兩字符串比較結果:result = %d\n", result );

    free( p );
    p = NULL;
    free( q );
    q = NULL;
}


void Homework()
{
    int *p = (int *)malloc( sizeof(int) * 3 );
    int *q = (int *)calloc( 3, sizeof(int) );
    p = memset( p, 0, 12 );

    for ( int i = 0; i < 3; i++ )
    {
        *(p + i) = arc4random() % 3 + 1 ;
        printf( "p = %d\n", *(p + i) );
        *(q + i) = arc4random() % 3 + 1 ;
        printf( "q = %d\n", *(q + i) );
    }
    if( 0 == memcmp( p, q, sizeof(int) * 3 ) )
    {
        printf( "GOOD!\n" );
    }
    else
    {
        printf( "Falied!\n" );
    }

    free( p );
    p = NULL;
    free( q );
    q = NULL;

}


int main(int argc, const char * argv[])
{
//    word();

//    callocAndRealloc();
//    memsetAndMemcpy();
    Homework();


//    //1、堆內存分配函數malloc(),此函數對應的返回值類型為 void * ,表示任意指針類型(泛型),其參數為所需開辟的空間的大小,以字節為單位。
//    int *p = malloc( sizeof( int ) * 4 );
//    printf( "%p\n", p );//分配的堆區 地址
//   
//    for( int i = 0; i < 4; i++ )
//    {
//        *(p + i) = arc4random() % 21 + 10;
//        printf( "address:%p -> content: %d\n", p + i, *(p + i) );
//    }
//   
//    *p = 3;
//    printf( "%d\n", *p );
//    int a = 3;
//    printf( "%p\n", &a );//和 堆區 的地址 比較後,發現比堆區的 地址長度大,
//   
//    free( p );
////    2、堆內存分配函數分配的存儲區域,在使用結束後應該調用標記刪除函數 free() 對其釋放。所謂標記刪除:表示當前使用的存儲區域可以被重新分配給其他需要的數據,但是在重新分配之前,他所保存的數據會一直存在。
//    p = NULL;
////   為了防止野指針出現,在標記刪除之後,表示這段空間不再使用,需要將指針指向空。
//   
//    printf( "%p\n", p );


//    char str[] = "abcdef123456ABCDEF789";
//    int size = 0;
//   
//   
//    for ( int i = 0; i < strlen( str ); i++ )
//    {
//        if ( str[i] >= '0' && str[i] <= '9' )
//        {
//            size++;
//        }
//    }
//    char *number = ( char * )malloc( sizeof( char ) * size );
//   
//    for ( int i = 0; i < strlen( str ); i++ )
//    {
//        if ( str[i] >= '0' && str[i] <= '9' )
//        {
//            *number = str[i];
//            number++;
//        }
//    }
//    printf( "%s\n", number - size );
//   
//    free( number - size ) ;
//    if( number != NULL )
//        number = NULL;

    return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved