// // main.m // LessonMemory // // Created by laouhn on 15/7/28. // Copyright (c) 2015年 池海涛. All rights reserved. // #import <Foundation/Foundation.h> struct student { char name[20]; char Sex; int age; }; typedef struct student Student; void fun2() { printf("sosososososos"); } int main(int argc, const char * argv[]) { #pragma mark--栈区:函数参数或者是局部变量存储的区域 /* >栈区的特点 1.分配原则:有高到底分配,由低到高存取 2.函数调用的过程就是出栈的过程.调用函数时入栈,系统会给该函数分配所需的空间;函数调用结束,出栈,系统会将分配的空间回收. 3.栈区空间是有限的 8M左右,之所以程序运行不会崩溃是因为----栈区空间在频繁的开辟以及释放 4.对于栈区空间的管理是由系统进行管理,不需要我们进行管理 int a = 10; int b = 10; int c = 10; printf("a的地址 %p b的地址%p c的地址 %p ",&a,&b,&c); */ #pragma mark---标记2 静态区:全局变量和静态变量存储的区域 /* 静态变量的特点: 1.静态变量只初始化一次 2.惊天变量如果不赋值,默认为0 3.静态变量空间一旦开辟,不会回收.在程序执行周期中都存在 静态区分为两部分:一部分存储赋值的全局变量和静态变量,另一部分存储没有赋初值的全局变量和静态变量 */ //static int num = 0;//由static 修饰的变量就是静态变量,局部静态变量. #pragma mark ----常量区 //常量区:存储常量,整型常量,浮点型常量,字符常量,字符串常量 //printf("%p ","iOS"); //char *str = "iPhone"; //str[0] = 'a';//常量区内容是只读的,不能被修改 //printf("%s ",str); #pragma mark ++++变量和常量 //变量:可以被修改的量,变量相当于一个容器,容器本身不发生变化,变化的是容器中存储的内容 //常量:不可以被改变的量 //const 修饰变量,一旦变量被const修饰,变量就会当做常量来使用. //口诀:看const修饰的是谁,const修饰谁,谁就不会发生改变,如果const修饰的内容中存在基本数据类型,将基本数据类型忽略掉 //面试题 //区分下列变量谁不会放生改变 // int a = 10; // int b = 30; // const int *p1 = &a; //1.const 修饰的是*p1 *p1 = 20 是错误的 *p1 处于只读状态 // a = 39; // printf("%d ",*p1); // p1 = &b; //2.const 修饰 p2,此时p2 处于只读状态,不能被重新赋值 // int *const p2 = &a; // //p2 = &b; // *p2 = 20; //3.const 修饰的 p3 ,此时*p3 处于只读状态,不能被重新赋值,此时与第一种情况相同 //int const *p3 = &a; //4.const 修饰 *p4 和p4,此时*p4 和p4都处于只读状态,都不能被重新赋值 //const int *const p4 = &a; //char str1[] = "iPhone"; //此时,常量去得'iPhone',拷贝一份给栈区的数组str进行保存 #pragma mark ---代码区:所有的语句编译成cpu指令存储在该区域 //printf("%p ",fun2); #pragma mark ----堆区:由我们(iOS开发人员)自主管理的区域(手动开辟,手动释放); //内存分配函数 //void *malloc(unsigned int size); //void *表示是无类型的指针,可以转化为任意类型的指针. //malloc函数的作用: 在堆区开辟指定size 个字节的空间,并把空间的首地址返回 //int *p = NULL; //指针变量p存储的是malloc出来的 堆区4个空间的地址 // p = malloc(4); // *p = 3; // printf("%d ", *p); // char *str = malloc(8); // printf("%p ", str);//指针变量 str中存储的是 堆区的地址 // printf("%p ",&str);//指针变量 str自己的地址 //char string[8200 * 1024] = {' '}; //iPhone 存储到该空间 // strcpy(str, "iPhone"); //strcpy(str, "Win Phone"); //该方式不合法, 因为拥有权限的空间只有 8 个字节,超出的不在字节控制范围之内 // int *a = malloc(4); // short *b = malloc(4); //a 分配了一块内存区域,可存放一个int 类型的数据, b 可以存放两个 short类型的数据 //printf("%s ",str); // // int *p = malloc(6); // *p = 7; // p[1] = 5; //*(p + 1) --p[1],不可以这样写,空间不够,指针只开辟了6个空间,而第二个元素需要4个字节占用了不合法的空间 //分配一个结构体内存 // Student *stu = malloc(sizeof(Student)); //分配一个结构体数组内存 //Student *stuArray = malloc(sizeof(Student) * 5); //void free(void *) ;//将指定地址所对应的空间释放(还给系统); //int *p = NULL; // p = malloc(6);//该空间,系统找不到了,照成内存泄露 //p = malloc(10); //free(p);//开辟之后,记得释放,如果不释放就会出现问题:内存泄露 //free(p);过度释放,照成程序崩溃 // p = NULL;//将空间释放之后,将指针置为NULL 防止野指针 // free(p); //不会报错,p 指向无效空间 //free(p); //free(p); //free 函数的作用是释放内存,内存释放是标记删除 //注意:释放一定要等到不使用的时候释放 //堆区内存问题: /* 1.野指针:访问一块没有权限的空间 2.过度释放:一块空间被释放了多次,----过度释放会照成程序立即crash 3.内存泄露:空间没有释放,造成内存的堆积,不会立即crash,存在安全隐患 */ /* int *p = malloc(5 * sizeof(int)); for (int i = 0; i < 5; i++) { *(p + i) = arc4random() % (40 - 20 + 1) + 20; } for (int i = 0 ; i < 5 - 1; i++) { for (int j = 0; j < 5 - 1 - i; j++) { if (*(p + j) > *(p + j + 1)) { int temp = *(p + j); *(p + j) = *(p + j + 1); *(p + j + 1) = temp; } } } for (int i = 0; i < 5; i++) { printf("%d ",*(p + i)); } //释放 手动开辟的空间 free(p); p = NULL; */ /* int i = 0; int k = 0; int j = 0; char str[] = "13s4sf3f24"; // int a[20] = {0}; char *p = NULL; while (str[i] != ' ') { if (str[i] >= '0' && str[i] <= '9') { //a[k++] = str[i]; k++; } i++; } i = 0; //分配空间,按照字符串进行处理 printf("数字个数=%d ",k); p = malloc((k + 1)*sizeof(int)); while (str[i] != 0) { if (str[i] >= '0' && str[i] <= '9') { *(p + j) = str[i]; j++; } i++; } *(p + j) = ' '; //最后添加 printf("%s ", p); free(p); p = NULL; */ //内存分配的另一个方式: calloc ---c是clear 的首字母,该函数的作用与malloc的作用,但是多了一步清零操作,该函数的执行效率比malloc低 //int *p = calloc(10,4);//第一参数代表分配空间的个数,第二个参数代表每个空间所占的字节数 //使用完,要释放 //free(p); //防止野指针 //p = NULL; //void *realloc(void *p,unsigned newSize); //内存重新分配的函数,先以之前的内存空间的首地址为基准进行重新划分.如果原来空间够用,直接返回原来空间的首地址,如果原来空间不够用,就重新寻找新的空间进行划分,并返回这块空间的地址,另外,realloc 内部集成了将之前内存free的操作. // char *p = malloc(10); // char *p1 = realloc(p, 20);//参数1 是之前空间的首地址,参数2是重新开辟空间的大小 // printf("p的地址是:%p p1的地址是:%p",p,p1); //内存操作函数 //----memset(void *,int,size_t),为malloc分配的空间执行清理操作,参数1代表从哪个位置开始清理,参数2代表清理时使用什么值代替,参数3代表清理多大的空间 // char *p = malloc(3); // memset(p, 0, 3);//从p的位置开始清理,清理3个字节,把每个字节上值赋值为0 // free(p); // p = NULL; // //----memcpy(void *dest,const void *source, size_t); 从source指向的内存开始 拷贝 size 个字节大小,到dest 指向的内存. // char str[] = "ZZS1570732"; // char string[] = "KONGKONG"; // memcpy(str, string, 4); // printf("%s %s",str,string); //int memcmp(const void *buf1,const void * buf2,unsigned int count);从给定得两个地址buf1,buf2,从开始进行比较,比较count个字节返回第一个不相等的字节空间的差值. //定义两个 整型指针,分别用malloc、calloc对其分配空间保存3个元素,malloc分配的空间用memset清零,随机对数组进行 赋值 随机范围1-3,赋值后用memcmp比较两个数组。如果相同打印Good!否则打印Failed... int *p = malloc(3 * sizeof(int)); int *p2 = calloc(3, 4); printf("%d",*p); printf("%d",*p2); memset(p, 0, 12); for (int i = 0; i < 3; i++) { p[i] = arc4random() % (3 - 1 + 1) + 1; p2[i] = arc4random() % (3 - 1 + 1) + 1; printf("%d %d ",p[i],p2[i]); } //比较 int result = memcmp(p,p2 , 12); if (result == 0) { printf("GOOD!"); }else printf("BAD!"); free(p); free(p2); p = NULL; p2 = NULL; return 0; } //释放