zoukankan      html  css  js  c++  java
  • C 入门 第十节 存储区

    int b = 5; // 存放在静态区 作用域是所有文件
    //  代码区
    void testMemory()
    {
        printf("代码区 ");
    }
    //static int b1 = 8; //作用域所有文件
    int main(int argc, const char * argv[]) {
    /*
        在计算机的内存中,可以分为5个区,每个区都有各自的操作以及管理内存的方式
        栈,堆,静态(全局),常量,代码区是按照内存笛子从小到大分配的
        代码区;

    //   打印各个存储区区域
    //    栈区:
        int a = 3;
    //    堆区:
        int *p = malloc(10);
    //    静态(全局):
        static int b = 5;
    //    常量:
        char *s = "iphone";
    //    函数存储在代码区:
        printf("栈区:%p ",&a);
        printf("堆区:%p ",p);
        printf("静态:%p ",&b);
        printf("常量:%p ",s);
        printf("代码:%p ",testMemory);
    */
    #pragma mark -----------栈区:函数参数或者是局部变量存储的区域----------
    /*
     
        栈区内存
        1 . 局部变量的存储空间,基本都在栈区,局部变量在函数,循环,分支中定义.
        2 . 栈区的存储空由高到低分配,从低到高存储.
        3 . 栈区内存由系统负责分配和回收,开发者没有管理的权限.定义局部变量时由系统分配存储空间,局部变量被销毁时由系统回收存储空间,但是存储空间中的数据没有被清空
        4 . 当函数,循环,分支执行结束后,局部变量的生命周期结束,不能在被使用,由系统销毁并回收存储空间.
        5 . 栈底,栈顶. 栈底是栈区的起始位置,先定义的变量所占用的内存从靠近栈底开始分配;后定义的变量所占的内存逐渐向栈顶分配.
        6 . 入栈,出栈. 入栈: 定义新的局部变量,分配存储空间;出栈: 局部变量被销毁,存储空间被收回
        7 . 栈的特点: 先进后出,后进先出;
        8 . 栈区会存在安全问题: 在函数中返回栈内存是不安全的
    */
        
    //    int a = 10;
    //    char b = 'a';
    //    double c = 3.4;
    //    printf("a的地址: %p ",&a);
    //    printf("b的地址: %p ",&b);
    //    printf("c的地址: %p ",&c);
    //
        
    /*
        常量区
        1 . 常量存储在常量区. 常量 字符串等等
        2 . 常量区存储空间是由系统分配和回收
        3 . 程序运行结束后,常量区的存储空间被收回
        4 . 常量区的数据只能被读取,不能被修改.修改会造成崩溃
    */
     
    #pragma mark -------静态区: 全局变量和静态变量存储的区域-----------
    /*
        静态区
        1. 全局变量,使用static修饰的局部变量,都存储在静态区.
        2. 静态区的存储空间由系统分配和回收.
        3. 程序运行结束后,静态区的存储空间被回收.静态区变量的生命周期跟程序一样长.
        4. 静态变量只能初始化一次,在编译时进行初始化,运行期可以修改
        5. 静态变量如果没有实质初始化,默认值为0;
    */
    //    static int b1 = 8; //静态变量,作用域是本文件
        
    #pragma mark  ---------代码区: 所有语句编译的cpu指令存储的区域--------------------
    /*
        代码区
        1. 由系统分配和回收
        2. 程序结束后,由系统回收分配过的存储空间
        3. 只能读,不能改
    */
     
    #pragma mark ---堆区: 由我们(ios开发工程师)自主管理的区域(手动开辟,手动释放)--------
    /*
        堆区
        1. 由开发者负责分配和回收
        2. 忘记回收内存会造成内存泄露
        3. 程序结束后会回收堆区内存,但是如果不能及时回收堆内存,程序运行期间可能会因为内存泄露造成堆内存被全部占用,程序无法运行.

     
        内存分配函数
        void *malloc(size)
        void * 表示的是无类型指针,可以转换任意类型指针.
        函数的作用: 在对区开辟指定size个字节的空间,并把空间的首地址返回

        int *p = NULL;
        p = malloc(sizeof(int));
        *p = 4;
        printf("%d ",*p);
        
        
        float *r = NULL;
        r = malloc(sizeof(float));
        *r = 8;
        printf("%.2f ",*r);

     //  分配存储空间存储数组元素,即分配多个连续的存储空间
        
     //  练习: 分配1个字符数组的内存,8个元素 "iPhone"
        char *p = malloc(sizeof(char) * 8);
        strcpy(p, "iphone");
        printf("%s ",p);

        
    //  练习: 分配一个整型的数组,10个元素,随机产生10个30~60之间的数,存储在分配的内存空间
        int *p = malloc(sizeof(int) *10);
        for (int i = 0; i < 10; i ++)
        {
            *(p+i) = arc4random()%(60 - 30 + 1) + 30;
        }
        
        for (int i = 0; i < 10; i ++)
        {
            printf("%d ",*(p+i));
        }
        printf(" ");

        
        
        typedef struct student
        {
            char name[20];
            int age;
        }Student;
        Student *p12 = malloc(sizeof(Student));
        strcpy(p12 -> name, "zhangsan");
        p12 -> age = 18;
        printf("%s %d ",p12 ->name,p12 -> age);
        
      释放开辟的空间
    //  void free(void *); 将指定的地址所对应的空间释放

        
        int *r = NULL;
        r = malloc(sizeof(int)); //这一块开辟的内存找不到,造成内存泄露
        r = malloc(sizeof(int));
        *r = 10;
        free(r); //开辟空间记得区释放,如果不释放,会出现内存问题:内存泄露
        
        r = NULL; //当空间回收之后,将指针置为null 安全,避免出现野指针,野指针: 指针指向不属于自己控制的存储单元
        free(r); //内存问题: 过度释放

    //  void *calloc(int n,size_t size);  在堆区开辟n*size个字节空间,并把空间地址返回,该函数会将空间进行清0操作,在效率上比malloc低
        
        char *str = NULL;
        str = (char*)calloc(10, sizeof(char));
        strcpy(str, "hello");
        printf("string is : %s ",str);
        free(str);
        str = NULL;
     */
    /*
        void *realloc(void*p,size_t newSize ); //在给定的地址空间上,如果当前指针空间足够,那么将他地址扩大,如果空间不足,那么重新找一块新的地址按照newSize大小分配空间.将原有数据从头到尾拷贝到新分配的内存区域,然后自动释放原来指针指向的内存区域,不需要free
        int *p_old = malloc(10);
        int *p_new = realloc(p_old, 150);
        printf("%p %p ",p_old,p_new);
    //  如果返回的地址和新地址不一样,那么系统会将原来的地址进行一次free,对于realloc()操作,只需要释放我们新的地址空间即可
     //   free(p_old);//过度释放
        free(p_new);
     
    //   void *memset(void *p,int c,size_t size) 从给定的地址开始size个字节直接重置为c,注意:该函数以字节单位进行操作.注要作用于清0.
     
        for (int i = 0; i < 3; i ++)
        {
            array[i] = i;
            printf("%d ",array[i]);
        }
        //全置为0
        memset(array, 0, 12);
        printf(" ");
        for (int i = 0; i < 3; i ++)
        {
            printf("%d ",array[i]);
        }
        printf(" ");
        char *p11 = malloc(10);
        memset(p11, 'a', 10);
        for (int i = 0; i < 10; i ++)
        {
            printf("%c ",p11[i]);
            
        }
        printf(" ");

    //  int memcmp(void *p,void *q,size_t Count); 从给定的俩个地址p和q开始比较count个字节,返回第一个不相等字节空间的差值
        int num1[3] = {1,2,3};
        int num2[3] = {1,2,2};
        int result = memcmp(num1, num2, 9);  // 9 : 比较的字节数
        printf("%d ",result);
     */
    //  void *memcpy(void *p, void *q, size_t n); 从指定的scorce指向的地址向dest指向的地址单元拷贝n个字节
        char wrongName[] = "bjs141148";
        char rightName[] = "15";
        memcpy(wrongName, "B", 1);
        memcpy(wrongName + 3, rightName, 2);
        printf("%s ",wrongName);

  • 相关阅读:
    HttpURLConnection用法详解
    Docker应用场景
    算法1
    Postman 使用详解
    Postman用法简介
    cookie和session
    HTTP简介
    get和post的区别
    git 同步非master分支
    SparseArray类
  • 原文地址:https://www.cnblogs.com/wangshuai-1129/p/5079090.html
Copyright © 2011-2022 走看看