当前位置:   article > 正文

iOS——内存动态分布_iphone的动态分区存储方法

iphone的动态分区存储方法
  1. 内存区域的划分(地址从高到底)

    • 栈区 // 反复的创建销毁
    • 堆区
    • 静态区(全局区)
    • 常量区
    • 代码区

1)栈区

*     栈管理数据的方式LIFO(后进先出)      FILO(先进后出)
*     局部变量:定义在函数内部的变量就叫做局部变量,局部变量都是存储在栈区。

       int a = 10;
       int b = 20;
      char c = ‘a’;     //  其中 a,b,c都是局部变量;

*     内存管理的时候,系统也是遵守内存对齐原则,因为这样可以提高内存的分配效率
*     局部变量存在于栈区,由系统为其分配空间和释放空间,开发人员不需要管理。
*     一个程序在内存中占据了大概7~8M的栈区内存,递归可以很快吃掉内存;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2)常量区:指针指向一个常量
char *str = “iPhone”; // 指针常量
printf(“%s\n”,str);

char string[20] = “iPhone”;
string[0] = ‘a’;
printf(“%s\n”,string);     //  “aPhone"
  • 1
  • 2
  • 3

常量区的内容只能访问,不能修改,常量区的数据也是由系统分配的,不需要开发人员管理。

3)静态区(全局区)

* 由static 修饰的变量存放在静态区,静态区的变量在整个程序运行过程中只能被初始化一次,如果没有认为初始化,这是系统默认初始化为零。
* 全局变量也是存放在静态区。
  • 1
  • 2

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个字节大小的空间,并把申请空的首地址返回;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

其他内存分配函数:

* 1. calloc (n,4)        两个参数的意思:表示申请n个size大小的空间,返回申请空间的首地址,但是他在申请空格的时候会坐一步处理,就是清除每一个字节里的内容,也就是清零操作,正是因为他多了这一步,执行的效率会比malloc低
  • 1

练习: 为一个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)   内存重新分配函数,第一个参数是地址(指针),第二个参数是重新分配的内存大小
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用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。
  • 1

// 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 的用法)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/877531
推荐阅读
相关标签
  

闽ICP备14008679号