您的位置:首页 > 移动开发 > IOS开发

iOS——内存动态分布

2015-12-28 19:36 375 查看
内存区域的划分(地址从高到底)

栈区 // 反复的创建销毁

堆区

静态区(全局区)

常量区

代码区

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 的用法)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: