欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言----内存区划分

程序员文章站 2022-07-07 22:34:18
一、栈区、堆区、静态区(全局区)、常量区、代码区: 1、栈:由系统根据数据类型所占字节数在此区域开辟存储空间,使用结束后,再由系统释放。 (系统分配,系统释放) 2、堆、手动...

一、栈区、堆区、静态区(全局区)、常量区、代码区:

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;
}