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 \n", 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 \n", strings[2]);

    //

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

    

    

    

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

    //    int c = 10;

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

    //

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

    //

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

    //

    

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

    //内存中的5分区

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

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

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

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

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

    

    //////

    

    

    //    int a = 10, b = 20;

    //

    //    printf("%d\n", 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\n", p);

    //

    //    strcpy(p, "Apple");

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

    //

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

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

    //    printf("%s\n", 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("\n");

    //    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] != ‘\0‘){

    //        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] != ‘\0‘){

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

    //            count++;

    //        }

    //        i++;

    //    }

    //    //开辟空间

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

    //    //存储字符

    //    j = 0;

    //    i = 0;

    //    while (str[i] != ‘\0‘){

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

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

    //            j++;

    //        }

    //        i++;

    //    }

    //    *(num + j) = ‘\0‘;

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

    //    free(num);

    //    num = NULL;

    //方法3

    //    i = 0, j = 0;

    //    while (str[i] != ‘\0‘){

    //        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("\nInput [%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\n",*(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;

}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。