zoukankan      html  css  js  c++  java
  • iOS开发之c语言基础Lesson-10 动态内存管理 上课笔记 与 试题练习

    //函数声明

    int max(int a, int b);

    char * getString(); 

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

        

        //////////////////Lesson 10 动态内存管理 课堂笔记 和 练习

        ///////复习上周所学

        /////////常量和变量的区别:

        //常量中的内容不能被修改,只能访问;

        //变量中存储的数据时可以随时修改的。

        //

        //const 关键字的作用: 修饰变量不可改变。当做常量使用

        

        //  const int a = 10;

        

        ////////以下变量谁可不变

        //口诀:看const修饰谁, 谁就不可变, 将数据类型 int 去掉 (const后面跟的变量,*也是一体的)

        //    int b = 30;

        //    const int *p1 = &b; //*p1不可变; p1指针变量,*p1指针变量指向的存储空间。const 修饰*p1, 不能通过指针变量*p1修改指向的存储空间上的数据,但是p1可以重新赋值。

        //

        //    int *const p2 = &b;//p2不可变,const修饰p2,p2中存储的数据不可更改,但是可以通过指针变量p2(使用*p2),修改指向的空间上的数据。

        //

        //    int const *p3 = &b;//*p3不可变,同p1

        //

        //    const int *const p4 = &b;//p4,*p4不可变

        

        

        

        /////////不同数据类型定义的变量所存储的内容:

        //int, short, long: 存储整数,整型数据。

        //float, double:存储小数,浮点型数据。

        //char:字符型数据。

        //char *, int *, short *: 存储地址

        //struct student: 存储结构体成员信息

        //struct student * :存储结构体变量的地址

        

        

        

        

        /////////指针数组

        //常量区上存储的数据不可更改。

        //    char *str1 = "iPhone"; //str1存储常量字符串 iPhone 首地址;

        //

        //    char *str2 = "Rose";

        //    char *str3 = "Tom";

        //    char *str4 = "Jack";

        //    char *str5 = "Android";

        //

        //    //交换指针变量

        //    char *temp = str2;

        //    str2 = str3;

        //    str3 = temp;

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

        //

        //

        //    char *strings[5] = {"iPhone", "Rose", "Tom", "Jack", "Android"};

        //    //strings[0] == str1

        //

        //

        //    char *tp = strings[1];

        //    strings[1] = strings[2];

        //    strings[2] = tp;

        //

        //    printf("%s ", strings[2]);

        //

        //    printf("%p, %p", str1, strings[0]); //同一个字符串,是一个地址

        

        

        

        ////////// * 的作用

        //    int c = 10;

        //    int *p = &c;  //定义指针变量时,*的作用只是为了告诉编译器,后面的变量是一个指针变量,用来存储地址。

        //

        //    *p = 30; //此时,* 的作用,是根据指针变量找到指向的存储空间,并且存储数据30

        //

        //    printf("%d ", *p);//同上

        //

        

        ////////////////////动态内存

        //内存中的5分区

        //1.栈区:主要存放局部变量或者数组,定义在函数内部,当函数调用时开辟空间,当函数结束后回收空间,内存有 系统 进行分配和回收。

        //2.堆区:堆区内存由 开发人员 手动开辟,手动释放。

        //3.全局、静态区:存放全局变量,以及静态变量; 程序运行时,开辟空间,程序运行结束空间回收。由 系统 进行管理。

        //4.常量区:存放常量;整型,浮点型,字符型,字符串型; 常量区空间上得内容不可修改,read-only

        //5.代码区:存放程序编译之后形成的CUP指令,告诉计算机程序如何运行。

        

        //////

        

        

        //    int a = 10, b = 20;

        //

        //    printf("%d ", max(a, b));

        //

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

        //

        

        ////////

        //如何在堆区空间上存放数据。

        //如何在堆区开辟空间

        //malloc在堆区开辟n个字节大小的空间,并且返回空间的首地址。返回值类型void *泛型,代表任意指针的类型。

        //如果申请 8 个字节的空间, 使用不同的指针类型变量接收, 存储的数据大小不同。

        //char *: 8个字符

        //int *: 2个整数

        //short *: 4个整数

        //long *: 1个整数

        //    char *p = malloc(7); //手动开辟空间

        //

        //    strcpy(p, "iPhone");

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

        //

        //    strcpy(p, "Apple");

        //    printf("%c ", *(p + 3));

        //

        //    free(p);    //手动释放空间, 释放时需要给定开始地址; 释放只是把空间还给系统,属于标记删除,不清楚内容。

        //    printf("%p ", p); //虽然释放了空间,但是p存的地址并没有清空

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

        //

        //    p = NULL;//清空指针变量中得地址,指向无效的空间

        //

        /////堆区空间常见的问题:

        /*

         1.野指针错误:访问一块没有权限的空间,没有获得空间的使用权。存在安全隐患;解决方案:当把空间还给系统之后,将指针变量中存储的地址清空 即:赋值NULL

         2.过度释放:对一块空间free多次,过度释放会立即导致crash.

         3.内存泄露:空间没有及时的释放,造成内存堆积。就是没有free; 安全隐患.

         */

        

        //开辟空间存储5个整数, 赋值10 - 20

        

        //    int *a = (int*)malloc(sizeof(int) * 5);

        //

        //    for (int i = 0; i < 5; i++) {

        //        *(a + i) = arc4random() % (20 - 10 + 1) + 10;

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

        //    }

        //

        //    for (int i = 0; i < 5 - 1; i++) {

        //        for ( int j = 0; j < 5 - 1 - i; j++) {

        //            if (*(a + j) < *(a + j + 1)) {

        //                int temp =*( a + j);

        //                *(a + j) = *(a + j + 1);

        //                *(a + j + 1) = temp;

        //            }

        //        }

        //    }

        //    printf(" ");

        //    for (int i = 0; i < 5; i++) {

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

        //    }

        //

        //    free(a);

        //    a = NULL;

        

        //    有⼀字符串,其中包含数字,提取其中的数字.要求动态分配内存保存

        //    char str[]= "lan5ou2015032056", *p = NULL;

        //

        //    char *a[20] = {0};

        //    int count = 0;

        //    int i = 0, j = 0;

        

        ////方法1

        //    while (str[i] != ''){

        //        if (str[i] >= '0' && str[i] <= '9') {

        //            a[j] = (char*) malloc(sizeof(char));

        //            count++;

        //            a[j] = &str[i];

        //            j++;

        //        }

        //        i++;

        //    }

        //    for (int i = 0; i < count; i++) {

        //        printf("%c ", *(a[i]));

        //    }

        /////方法2

        //   // 获得数字个数

        //   i = 0;

        //    while (str[i] != ''){

        //        if (str[i] >= '0' && str[i] <= '9') {

        //            count++;

        //        }

        //        i++;

        //    }

        //    //开辟空间

        //    char *num = malloc(count + 1);

        //    //存储字符

        //    j = 0;

        //    i = 0;

        //    while (str[i] != ''){

        //        if (str[i] >= '0' && str[i] <= '9') {

        //             *(num + j) = str[i];

        //            j++;

        //        }

        //        i++;

        //    }

        //    *(num + j) = '';

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

        //    free(num);

        //    num = NULL;

        //方法3

        //    i = 0, j = 0;

        //    while (str[i] != ''){

        //        if (str[i] >= '0' && str[i] <= '9') {

        //            p =  realloc(p, sizeof(char));

        //            count++;

        //            *(p + j) = str[i];

        //            j++;

        //        }

        //        i++;

        //    }

        //

        //    printf("数字个数:%d, %s ",count, p);

        //    free(p);

        //    p = NULL;

        

        //2. 输⼊入3个学员的姓名,动态分配内存保存学员姓名,并在最后输出

        //存储3个单词,意味着需要开辟3次空间,每次开辟空间都会返回对应的首地址, 所有为了存储3个地址,定义指针数组存储。

        //    char *word[3] = {0};

        //    char temp[20] = {0}; //存储控制台输入的字符串

        //

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

        //        printf(" Input [%d] name :", i + 1);

        //        scanf("%s",temp);

        //        word[i] = malloc(strlen(temp) + 1);//根据输入的字符串动态在堆区分配空间

        //        strcpy(word[i], temp);

        //    }

        //

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

        //        printf("%s ", *(word + i));

        //        free(word[i]);

        //        word[i] = NULL;

        //    }

        

        ////////其他内存分配函数

        //////calloc(n, size_t)  c---clear 多了一步空间数据的清理操作,但是清理操作效率较低。

        //    //分配n个size⼤大⼩小的空间,并且把该内存上的所有字节清零。 分配n个size大小的空间

        //    int *ptr = calloc(5, 4);

        //

        //    free(ptr);

        //    ptr = NULL;

        //

        //

        //    //////realloc 内存重新分配函数

        //    char *pstr = malloc(10);

        //    //10个空间不够,重新分配20个,不是追加

        //    char *pstr1 = realloc(pstr, 200);  //工作原理:先以之前的开始地址作为基准,重新分配新的空间,如果此时发现剩余空间不足,会寻找新的空间。此时返回的地址,就和之前不一样的,另外realloc内部集成了将之前空间free的操作。

        //    printf("%p, %p", pstr, pstr1);

        //    free(pstr1);   //只需释放realloc的空间即可。

        //    pstr1 = NULL;

        //    pstr = NULL;

        //    

        

        

        ///////内存操作函数

        // void *memset(void *s , int c , size_t n)    

        // 从s指向的内存开始初始化n个字节的内容为c

        

        

        //    int memcmp(const void *buf1, const void *buf2, unsigned int count)

        //    

        //    ⽐比较buf1和buf2指向的内存是否相同,⽐比较count个字节

        

        

        

        //    void *memcpy(void *dest,const void*source , size_t n)

        //    

        //    从source指向的内存开始拷⻉贝到dest,拷⻉贝n个字节

        

        

        // 定义两个整型指针,分别⽤用malloc、calloc对其分配空间保存3个元 素,malloc分配的空间⽤用memset清零,随机对数组进⾏行赋值随机范 围1-3,赋值后⽤用memcmp⽐比较两个数组。如果相同打印Good!否则 打印Failed...

        //

        //    int *ip1 = (int *)malloc(3 * sizeof(int));

        //    int *ip2 = (int *)calloc(3, 4);

        //

        //    memset(ip1, 0, 12);  //清 0 操作

        //

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

        //        *(ip1 + i) = arc4random() % 3 + 1;

        //        *(ip2 + i) = arc4random() % 3 + 1;

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

        //

        //    }

        //    if ( memcmp(ip1, ip2, 1) == 0) {

        //        printf("GOOD");

        //    }else{

        //        printf("Failed");

        //    }

        //    

      

       return 0;

    }

    //函数实现

    int max(int a, int b){

        return a > b ? a : b;

    }

    //char string[] = "Welcome to Lanou iOS!"; //放在这里是可以,不过不太安全

    char *getString(){

        // char string[] = "Welcome to Lanou iOS!";  // //数组string,是在函数内部定义的,属于局部变量,存储在栈区,当函数执行结束,数组空间被系统回收。外界拿到地址,将访问一块已经回收的空间。所以,要想安全的返回,必须保证返回之后空间还在。

        

        // static char string[] = "Welcome to Lanou iOS!"; //设置成静态数组

        

        char *string = "Welcome to Lanou iOS!";     //返回的是常量区Welcome 。。。。,首地址;

        

        return string;

    }

  • 相关阅读:
    祝贺我的博客訪问量过万(訪问量:10260次)
    【LeetCode-面试算法经典-Java实现】【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】
    Hibernate之HQL检索(查询)方式
    使用Nexus搭建Maven仓库
    poj2151之概率DP
    《从零開始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射
    D3D 点列练习
    poj 1733 Parity game
    命令行參数
    高速乘法
  • 原文地址:https://www.cnblogs.com/zhaoashen/p/4382300.html
Copyright © 2011-2022 走看看