zoukankan      html  css  js  c++  java
  • C语言5种存储区域

    C语言5种存储区域

    转发至:http://www.mamicode.com/info-detail-927635.html

    系统为了管理内存 把内存划分了几个区域

         1> 栈区

         栈区之中的数据在栈区之中以栈的形式进行存储.

         栈区的特点:数据是先进后出,

         放在栈区里面存放的是局部变量.(例如定义在函数内部的变量)

         栈区之中的数据(局部变量)的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理

    2> 堆区

         高效的使用内存

         这里的内存可以由程序员自己手动管理 高效的使用内存  例如: 申请内存 释放内存.优化内存 ARC

         申请内存的函数 malloc()  memary alloc  申请内存空间

         void *mallc(size_t);

         

         函数名:malloc

         

         返回值: void *   (泛指针类型 可以轻松的转换为任意类型的指针)    

                         返回一个指向新开辟的的存空间的首地址 

                         类型是一个泛指针(可以根据接受者 动态的转换).

         

         参数: size_t  申请动态空间的字节数的大小. 即:你要开辟多大的空间. 例如开辟一个整形的变量的存储空间(在堆区之中)  malloc(4);

         

         int *p = malloc(4);

         释放内存的函数 free(p);// p 是你 刚刚使用 开辟空间函数返回的内存空间首地址的的指针接受者

         最后还要将 p = NULL; 否则会出现野指针错误! 

         void *calloc(unsigned n,unsigned size);(10 * 4)

         申请 count * size 个字节  count 是个数 size 是每一个占用的字节数 

         并且将申请到的内存之前的残留数据清空,效率比malloc 要低,但是更安全.

         

         例如 :开辟十个整型数据的空间

          

         int *p = calloc(10,sizeof(int));

         

         void * realloc(<#void *#>, <#size_t#>);  重新分配内存空间.

         realloc(p, size);

         从指针p的位置 重新申请size个字节. 返回一个 泛类型的指针.

          从p的位置开始申请,如果后面有size 个字节可以使用,就直接申请;如果没有,就去内存之中找一块连续的size字节,找到就直接申请,并且在申请之前,释放掉以前申请到的内存. 返回新的指针.

         memset(void *,int ,size_t);

         memset(p,c,n);

         从指针的p的位置开始,初始化n个字节的内容并且把内容改为 C;

         //memccpy(<#void *#>, <#const void *#>, <#int#>, <#size_t#>)

           memccpy(dest, source, <#int#>, <#size_t#>)

           memcpy(dest, source, n);

         从指针source 的位置开始,向指针dest的位置,拷贝n个字节的内容.

     3> 静态区(全局区)

         静态区存放的是: 全局变量(定义在函数外部的变量 例如在主函数上面 定义的变量) 和 静态变量

         static 类型的变量有什么特点:(只初始化一次(初始化是 在定义的时候辅助),不初始化的话,默认为零.)

         静态区内存是由系统管理的. 

         一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放

    4> 常量区

         

         常量区存放: 常量(程序在运行的期间不能够被改变的量 例如: 10 ‘a‘ 1.12 "ios", 数组的名字)

         常量区的内容是只能读的 不能被修改的的.

         

         区别一下下面的代码:

         char *p = "kpkoj";

         等价于 char *p; p = "kpkoj";

         此时char类型的指针p存放的是常量字符串的首地址 ("kpkoj"(存放在常量区)的首地址)

         所以此时p指向的内容不能够被修改,只能被读取  即*p的值只能被读取,不能被修改.但是可以重新的将指针变量p指向新得地址. 

         例如在上面这个的操作的基础之上 在将p赋上新的值 p = "ddvdd";(拷贝的是地址此时又指向了一个新的常量的首地址)

     

    这个情况:  char str[] = "iOS";

         这个是字符数组 是将常量字符串"iOS"的内容拷贝到栈区的字符数组之中 ,所以可以修改数组内的内容.例如: str[0]= ‘d‘;

         但是str(数组名) 是一个常量的地址已经初始化,就不能被重定向(更改他的指向),所以只能通过下标或者什么的对其数组中的某个元素进行修改,区别上面的的指针情况.

         常量的内存也是由系统管理的.

    5> 代码区

         内存还是由系统控制的

         代码区的存放 :程序中的函数编译后cpu指令

         代码区的地址:函数的地址,程序的入口地址.程序的名字.

         栈区内存地址编号由高到低(栈区 -> 代码区).

    //    int *h = malloc(4);//开辟一个堆区的地址 大小为 4

    //    *h = 1024;//向堆区内存空间之中写入数据 1024

    //    

    //    printf("堆区的地址%p,  %d " , h , *h);

    //    //在堆区之中 存入 "iphone 6s";

    //    

    //    char *ch = malloc(sizeof("iphone 6s"));

    ////    ch = "iphone 6s";

    ////    ch = "dddd";//这样只是将指针重新指向.而,新开辟的内存空间已经没有指向,造成内存没有指向  内存泄露

    //    strcpy(ch , "iphone 6s");//将常量区的内容拷贝到指向的刚刚开辟的内存区域!.

    ////    ch[0] = ‘1‘;//这里可以被修改 因为他指向的内存区域是栈区 不是  常量区域

    ////    ch = "iphone 6s";//指向常量区的地址.

    ////    ch[0] = ‘1‘;//这样就不能修改 ch[0]的内容 因为 ch指向的是一块常量地址,不能被修改. 上面已经有详细的阐述了.

    //    printf("%s " , ch);

    //    

    //    

    //    

    //    strcpy(ch, ch + 2);

    //    printf("%s ",ch);

    //    

    //    

    //    int *p3 = malloc(4);

    //    printf("%p " , p3);//申请内存的堆区地址.

    //    printf("%p " , &p3);//指针变量的栈区的地址

    //    

    //    //同样的 开辟内存之后一定要记得释放 否则容易造成 内存泄露

    //    //内存泄露: 内存一直被占用 得不到释放.

    //    free(p3);//内存释放函数 free(开辟的内存的首地址)  只是将内存标记为可用而没有将里面的内容抹掉

    //    p3 = NULL;//记得安全的做法 将指针指向空 NULL 要不是就是野指针了.错误了

    //    // 使用动态内存分配的知识,在内存存放10个整数,随机数范围[2 , 399];

    //    

    //    int *open = malloc(sizeof(int) * 10);//分配一段连续的空间.

    //    int *lh = open;

    //    for (int i = 0; i < 10; i++)

    //    {

    //    *(open + i) = arc4random() % (399 - 2 + 1) + 2;//向下偏移就可以了,因为下面的也是开辟的动态内存空间 open++;

    //        open[i] = arc4random() % (399 - 2 + 1) + 2;

    //        

    //        printf("%d  ",*(open + i));

    //    }

    //    printf(" ");

    //    

    //    BOOL flags = YES;

    //    int temp;

    //    for (int o = 0; o < 9 && flags; o++)

    //    {

    //        flags = NO;

    //        for (int i = 0; i < 9 - o; i++)

    //        {

    //            if (*(open + i) > *(open + 1 + i) )

    //            {

    //                temp = *(open + i);

    //                *(open + i) = *(open + 1 + i );

    //                *(open + i + 1) = temp;

    //                flags = YES;

    //            }

    //        }

    //    }

    //    for (int i = 0; i < 10; i++)

    //    {

    //        printf("%d  " , open[i]);

    //    }

    //    printf(" ");

    //    free(open);

    //    open = NULL;

    //    const int b = 0;

    //    char *p = "iOS"; //定义了一个栈区的指针变量 存放着 常量区的地址.

    ////    p[0] = ‘f‘;

    ////    *p = ‘m‘;

    //    p = "ddd";

    //    puts(p);

    //    printf("常量去的地址%p ",p);

    //    int a = 10;

    //    static int k = 20;//静态变量.

    //    printf("静态变量的地址  p   %p " , &k);

    //    printf("静态区的地址:%p " , &b);

    //    printf("栈区的地址:%p " , &a);

    //    printf("代码区的地址:%p " , main);

    //    for(int i = 0 ; i < 100 ; i++ )

    //    {

    ////        int n = i;

    ////        static int n = 1; //只能被 定义和初始化一次.  存放在静态区   没有赋初值. 而且初始化的时候一定要 赋一个常量 不能赋值一个 变量.

    ////        printf("%d ",n);

    //    }

        

        

    //    char ch[] = "jkjl3jo342pook25l414fe4op0kfe1";

    //    int i , sum;

    //    i = sum = 0;

    //    while (ch[i] != ‘‘)

    //    {

    //        if (ch[i] >= ‘0‘ && ch[i] <= ‘9‘)

    //        {

    //            sum++;

    //        }

    //        i++;

    //    }

    //    printf("%d " , sum);

    //    //数组定义的时候,元素的个数必须是确定的值  不能出现变量的不确定

    //    char *p = malloc(sum + 1);

    //    i = sum = 0;

    //    while (ch[i] != ‘‘)

    //    {

    //        if (ch[i] >= ‘0‘ && ch[i] <= ‘9‘)

    //        {

    //            *(p + sum) = ch[i];

    //            sum++;

    //        }

    //        i++;

    //    }

    //    p[sum] = ‘‘;

    //    printf("%s " , p);

    //    free(p);

    //    p = NULL;

    //    memccpy(<#void *#>, <#const void *#>, <#int#>, <#size_t#>)

    //    memcpy(<#void *#>, <#const void *#>, <#size_t#>)

        

        

    //    char *p = malloc(4);

    //    memset(p, 66, 2);

    //    printf("%s ",p);

    //    char str1[] = "sdfsafdaf";

    //    char str2[] = "564545121";

    //    memcpy(str1, str2, 3);

    //    printf("%s " ,str1);

    //    memcmp(p1, p2, n);

    //    内存的比较. 比较p1和p2 指向的内存之中的内容是否相等 ,比较n个字节的长度 相同的返回0,不同的返回差值.

    //    int *p1 = malloc(4);

    //    *p1 = 8 ;

    //    int *p2 = malloc(4);

    //    *p2 = 3;

    //    int result = memcmp(p1, p2, 1);

    //    printf("%d ",result);

        

        int *p1 , *p2;

        p1 = malloc(3 * sizeof(int));

        p2 = calloc(3 , sizeof(int));

        memset(p1, 0, 3*sizeof(int));

        for (int i = 0; i < 3; i++)

        {

            *(p1 + i) = arc4random()%(3 - 1 + 1) + 1;

            *(p2 + i) = arc4random()%(3 - 1 + 1) + 1;

            printf("%d  %d",*(p1 + i),*(p2 + i));

    //        *(p1 + i) = 1;

    //        *(p2 + i) = 1;

            printf(" ");

        }

        if (memcmp(p1, p2, 16)==0)

        {

            printf("good ");

        }

        else

            printf("Failed ");

        free(p1);

        free(p2);

        p1 = p2 = NULL;

  • 相关阅读:
    活着的目标
    Online Judge(OJ)搭建——2、数据库,SQL语句
    《Docker 实战》第三章 Docker Hub 寻宝游戏
    2017年计划
    IDEA 问题 & 解决
    IDEA 自动化配置
    bzoj 3796: Mushroom追妹纸【二分+后缀数组+st表】
    CF487E Tourists【圆方树+tarjan+multiset+树剖+线段树】
    bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】
    bzoj 4316: 小C的独立集【仙人掌dp】
  • 原文地址:https://www.cnblogs.com/pruple/p/5640882.html
Copyright © 2011-2022 走看看