iOS——内存动态分布
2015-12-28 19:36
375 查看
内存区域的划分(地址从高到底)
栈区 // 反复的创建销毁
堆区
静态区(全局区)
常量区
代码区
1)栈区
2)常量区:指针指向一个常量
char *str = “iPhone”; // 指针常量
printf(“%s\n”,str);
常量区的内容只能访问,不能修改,常量区的数据也是由系统分配的,不需要开发人员管理。
3)静态区(全局区)
static int d;
printf(“%d\n”,d);
printf(“常量区地址:%p\n”,&number);
printf(“%p\n”,&d);
for (int i = 0; i < 5; i++) {
static int count = 0;
printf(“%d\n”,count);
count++;
}
4)代码区:程序中运行的函数或者变量等等语句都会被编译成CPU指令,存放在代码区
系统提供的函数由于使用比较频繁,我们把它们存放到栈区,原因是栈区的内容会被反复的创建销毁,不需要我们去管理内存,还有一点就是因为栈区的内存开辟和释放都是非常迅速。
int arr[5] = {1,2,3,4,5};
int *p1 = arr;
printf(“%p\n%p\n”,p1,arr);
5)堆区:是唯一一块开发者能够控制的内存区域,这块区域的内存我们要手动申请,并且手动释放。
char *p = malloc(8); // p内存储的是这8个空间的首地址。
strcpy(p, “iPhone”); // 为数组赋值。
printf(“%s\n”,p);
printf(“堆区的地址:%p\n”,p);
p[0] = ‘a’;
printf(“%s\n”,p);
free(p); // 释放掉p指向的堆区空间,只是标记删除,不清空里边的内容。
// free(p); 过度释放,释放多次,会造成crash(崩溃);
// printf(“%p\n”,p);
p = NULL; // 指向无效空间,防止野指针错误 确保安全。
(**)练习6: 有一个已知的字符串,其中包含数字字符,提取其中的数字,存储到堆区,动态开辟内存;
其他内存分配函数:
练习: 为一个5个元素的整形数组分配空间,存储数据,元素的范围是[30 50];
使用realloc重新分配空间的时候,如果在原有空间的基础上可以连续在增加(n-原来大小)个空间,指针的指向不会改变,如果这时不可以连续增加,则会将之前的空间给释放掉,然后再去其他堆区的其他位置开辟连续n个空间大小的内存,这时指针的指向也改变了
int *p6 = malloc(12);
*p6 = 10;
*(p6+1) = 20;
*(p6+2) = 30;
printf(“之前的地址:%p\n”,p6);
// 重新申请空间的大小
p6 = realloc(p6, 20);
printf(“之后的地址:%p\n”,p6);
*(p6 +3) = 40;
*(p6 +4) = 50;
// 重新分配的空间会把之前空间里的内容给拷贝过来,放在相应的位置。
for (int i = 0; i < 5; i ++) {
printf(“%d “,*(p6 + i));
}
free(p6);
p6 = NULL
内存操作的其他函数
// memcpy(dest, source, n)// 从源指针开始位置,向目的指针拷贝n个字节的数据 // 往dest里拷贝
栈区 // 反复的创建销毁
堆区
静态区(全局区)
常量区
代码区
1)栈区
* 栈管理数据的方式LIFO(后进先出) FILO(先进后出) * 局部变量:定义在函数内部的变量就叫做局部变量,局部变量都是存储在栈区。 int a = 10; int b = 20; char c = ‘a’; // 其中 a,b,c都是局部变量; * 内存管理的时候,系统也是遵守内存对齐原则,因为这样可以提高内存的分配效率 * 局部变量存在于栈区,由系统为其分配空间和释放空间,开发人员不需要管理。 * 一个程序在内存中占据了大概7~8M的栈区内存,递归可以很快吃掉内存;
2)常量区:指针指向一个常量
char *str = “iPhone”; // 指针常量
printf(“%s\n”,str);
char string[20] = “iPhone”; string[0] = ‘a’; printf(“%s\n”,string); // “aPhone"
常量区的内容只能访问,不能修改,常量区的数据也是由系统分配的,不需要开发人员管理。
3)静态区(全局区)
* 由static 修饰的变量存放在静态区,静态区的变量在整个程序运行过程中只能被初始化一次,如果没有认为初始化,这是系统默认初始化为零。 * 全局变量也是存放在静态区。
static int d;
printf(“%d\n”,d);
printf(“常量区地址:%p\n”,&number);
printf(“%p\n”,&d);
for (int i = 0; i < 5; i++) {
static int count = 0;
printf(“%d\n”,count);
count++;
}
4)代码区:程序中运行的函数或者变量等等语句都会被编译成CPU指令,存放在代码区
系统提供的函数由于使用比较频繁,我们把它们存放到栈区,原因是栈区的内容会被反复的创建销毁,不需要我们去管理内存,还有一点就是因为栈区的内存开辟和释放都是非常迅速。
int arr[5] = {1,2,3,4,5};
int *p1 = arr;
printf(“%p\n%p\n”,p1,arr);
5)堆区:是唯一一块开发者能够控制的内存区域,这块区域的内存我们要手动申请,并且手动释放。
// 如何管理堆区的内存? // malloc // void *malloc(size_t); // void * ,泛类型,void *返回的指针可以赋值给任何类型的指针,int *,float *,char *,short * // size_t 代表申请多少个字节大小的内存空间 // malloc的作用: 申请size个字节大小的空间,并把申请空的首地址返回;
char *p = malloc(8); // p内存储的是这8个空间的首地址。
strcpy(p, “iPhone”); // 为数组赋值。
printf(“%s\n”,p);
printf(“堆区的地址:%p\n”,p);
p[0] = ‘a’;
printf(“%s\n”,p);
free(p); // 释放掉p指向的堆区空间,只是标记删除,不清空里边的内容。
// free(p); 过度释放,释放多次,会造成crash(崩溃);
// printf(“%p\n”,p);
p = NULL; // 指向无效空间,防止野指针错误 确保安全。
(**)练习6: 有一个已知的字符串,其中包含数字字符,提取其中的数字,存储到堆区,动态开辟内存;
char st[] = "lanou999zhegnzhou110"; int i = 0; int n = 0; while (st[i] != '\0') { // 这一个判断函数为了记录这个字符串中数字的数量。 if (st[i] >= '0' && st[i] <= '9') { n++; }i++; } char *m = malloc(n+1); // +1 的目的是为了给存储\0 int z = 0; int index = 0; // 记录m指向内存空间每一个字符下标的位置 while (st[z] != '\0') { if (st[z] >= '0' && st[z] <= '9') { *(m+index) = st[z]; index++; // 转向下一个元素 }z++; } *(m + index) = '\0'; printf("%s\n",m); free(m); m = NULL;
其他内存分配函数:
* 1. calloc (n,4) 两个参数的意思:表示申请n个size大小的空间,返回申请空间的首地址,但是他在申请空格的时候会坐一步处理,就是清除每一个字节里的内容,也就是清零操作,正是因为他多了这一步,执行的效率会比malloc低
练习: 为一个5个元素的整形数组分配空间,存储数据,元素的范围是[30 50];
int *p5 = calloc(5, sizeof(int)); for (int i = 0; i<5; i++) { *(p5+i) = arc4random_uniform(50-30+1)+30; printf("%d\n",*(p5 + i)); } free(p5); p5 = NULL; * 2. realloc(p,n) 内存重新分配函数,第一个参数是地址(指针),第二个参数是重新分配的内存大小
使用realloc重新分配空间的时候,如果在原有空间的基础上可以连续在增加(n-原来大小)个空间,指针的指向不会改变,如果这时不可以连续增加,则会将之前的空间给释放掉,然后再去其他堆区的其他位置开辟连续n个空间大小的内存,这时指针的指向也改变了
int *p6 = malloc(12);
*p6 = 10;
*(p6+1) = 20;
*(p6+2) = 30;
printf(“之前的地址:%p\n”,p6);
// 重新申请空间的大小
p6 = realloc(p6, 20);
printf(“之后的地址:%p\n”,p6);
*(p6 +3) = 40;
*(p6 +4) = 50;
// 重新分配的空间会把之前空间里的内容给拷贝过来,放在相应的位置。
for (int i = 0; i < 5; i ++) {
printf(“%d “,*(p6 + i));
}
free(p6);
p6 = NULL
内存操作的其他函数
* 3.memset(开始地址,n,size) 给定一个开始地址,将size字节的空间大小内的数据置为n,如果n为零,size为10,就是把10个字节中的数据置为0。
// memcpy(dest, source, n)// 从源指针开始位置,向目的指针拷贝n个字节的数据 // 往dest里拷贝
char str1[] = "ABC"; char str2[] = "123"; memcpy(str1, str2, 2); printf("%s\n",str1); // memcmp (p1,p2,n) 比较p1和p2指向内存里的内容是否相同,比较n个字节,返回值是0,相等。不同的时候,返回差值。比较的过程是逐个字节的比较,返回第一对对应字节位置不相同数据的差值(参加 strcmp 的用法)
相关文章推荐
- iOS——函数
- iOS——指针
- iOS——结构体
- iOS——一维数组
- ios开发常用的宏定义
- iOS开发中的公共方法
- 对iOS锁的一些研究
- iOS同步对象性能对比(iOS锁性能对比)
- iOS Provisioning Profile(Certificate)与Code Signing详解
- iOS如何在多台机器上共享iOS证书
- iOS 9下的shareSDK集成的常见问题及解决方案
- animation - 6
- iOS SEL的简单总结
- iOS并发编程-锁
- iOS 开始页面实现
- iOS代码混淆
- IOS Quartz 各种绘制图形用法---实现画图片、写文字、画线、椭圆、矩形、棱形等
- iOS进程与线程的区别
- IOS CGContext用法
- iOS小问题--使用NSPredicate比较两个数组中相同(不同)的元素