动态内存分配, C语言,动态内存分配,栈区,堆区,静态区,常量区,代码区
动态内存分配
系统为了有效地管理内存,把内存划分为:
1.栈区
2.堆区
3.静态区(全局区)
4.常量区
5.代码区
注:内存地址编号由高到低(栈区->代码区)
1.栈区
栈区的数据以栈的形势存储
栈,先进后出
栈区存放的数据:局部变量(定义在函数内部的变量)
栈区的内存油系统自动管理的(分配内存,回收内存),不需要开发人员管理
栈区只有8MB,容易出现栈溢出
stackoverflow网站
栈区的内存,函数结束时,被收回
int a = 10;//栈区分配4个字节 printf("栈区地址: %p\n", &a);
2.堆区
由开发人员手动管理(申请内存,释放内存)
堆区空间比较大
申请内存函数
void*malloc(<#size_t#>)
返回值类型:void*,空指针类型(泛指针类型),可以转化成任意的指针类型
函数名: malloc
参数: size_t,unsignedlong,申请的字节数
//从堆区申请4个字节的内存, 并返回首地址 int *p1 = malloc(4); //向堆区存入数据1024 *p1 = 1024; printf("%d\n", *p1); printf("堆区地址: %p\n", p1); //在堆区存入"iPhone 6s" char *p2 = malloc(10); strcpy(p2, "iPhone 6s"); printf("%s\n", p2); printf("堆区地址: %p\n", p2); *p2 = 68; printf("%s\n", p2); p2[3] = '\0'; printf("%s\n", p2); strcpy(p2 + 2, "abcd");//字符串最后一个是'\0', 会一起拷贝进去, 字符串结束 printf("%s\n", p2); strcpy(p2, p2 + 2); printf("%s\n", p2); printf("%c\n", p2[5]);
内存泄露:内存一直被占用,而得不到释放
内存释放的函数
voidfree(<#void *#>)
int *p3 = malloc(4);//定义一个栈区指针变量, 存放栈区的首地址 *p3 = 123;//把常量区的数据123, 拷贝到堆区 free(p3);//把堆区的空间, 标记释放 p3 = NULL;//因为指针p3存放有堆区的地址, 还可以通过地址访问堆区, 为了安全起见, 把指针p3置空 //使用动态内存分配的知识, 在内存中存10个整数, 随机赋值[2, 10] int *p4 = malloc(sizeof(int) * 10); for (int i = 0; i < 10; i++) { //1 *(p4 + i) = arc4random() % 9 + 2; printf("%d ", *(p4 + i)); //2 // p4[i] = arc4random() % 9 + 2; // printf("%d ", p4[i]); //3. // *p4 = arc4random() % 9 + 2; // p4++; // printf("%d ", *p4); } printf("\n"); //冒泡排序 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9 - i; j++) { if (p4[j] > p4[j + 1]) { int temp = p4[j]; p4[j] = p4[j + 1]; p4[j + 1] = temp; } } } for (int i = 0; i < 10; i++) { printf("%d ", p4[i]); } free(p4); p4 = NULL; printf("\n");
3.静态区(全局区)
存放数据:全局变量(定义在函数外部的变量)和静态变量(static修饰的变量)
静态区的内存由系统控制
静态区的内存,一旦分配,就一直占用,直到程序结束
#import <Foundation/Foundation.h> int d = 50; int main(int argc, const char * argv[]) { printf("静态区地址: %p\n", &d); static int e = 70;//静态变量 //a.存在静态区内 printf("静态区地址: %p\n", &e); //b.只会被初始化一次 for (int i = 0; i < 10; i++) { static int n = 100;//只执行一次 printf("%d ", n++); } printf("\n"); //c.不赋初值, 默认0 static int f; printf("%d\n", f); return 0; }
4.常量区
存放数据:常量(1,3.14,'a',"iOS")
常量区的内容只能读不能修改
常量区由系统管理
char *p = "iOS"; printf("常量区地址: %p\n", p); //*p = 'm';//error printf("%s\n", p);
//函数名就是函数的首地址 printf("代码区地址: %p\n", hello);
5.代码区
存放数据:程序中的函数编译后的指令
代码区由系统控制
//函数名就是函数的首地址 printf("代码区地址: %p\n", hello);
把字符串"1ab2c3d45e67g8h9"中的数字提取出来,形成新的字符串,新的字符串要求存放在堆区
提示:先求数字的个数,再根据个数开辟内存空间
char str[] = "1ab2c3d45e67g8h9"; int count = 0; int i = 0; while (str[i] != '\0') { //判断字符是不是数字字符 if (str[i] >= '0' && str[i] <= '9') { count++; } i++; } printf("count = %d\n", count); //在堆区申请空间 char *p5 = malloc(count + 1); //遍历字符串 int j = 0; int k = 0; while (str[j] != '\0') { //判断字符是不是数字字符 if (str[j] >= '0' && str[j] <= '9') { *(p5 + k) = str[j]; k++; } j++; } //最后补上'\0' p5[k] = '\0'; printf("%s\n", p5); free(p5); p5 = NULL;
处理内存函数
void*calloc(n, size)
1.申请n * size个字节,并返回内存的首地址,申请到内存后,会把内存中的数据清空
2.比起maloc,效率低,安全性高
int *p6 = calloc(10, sizeof(int)); free(p6); p6 = NULL;
void*realloc(p, size)
1.从指针p的位置,重新申请size个字节
2.从指针p的位置开始申请,如果后面有size个字节可以使用,就直接申请;如果没有,就去内存中找一块连续size个字节,找到就直接申请,并且把之前申请的内存释放
int *p7 = malloc(4); printf("%p\n", p7); int *p8 = realloc(p7, 800); printf("%p\n", p8);
memset(p, c, n)
从指针p的位置开始,初始化n个字节的内容,并且把内容设置为c
char *p9 = malloc(4); memset(p9, 66, 2); printf("%s\n", p9);
memcpy(p1, p2, n)
从指针p2的位置开始,向指针p1的位置,拷贝n个字节的内容
char str1[] = "ABCDEFG"; char str2[] = "1234567"; memcpy(str1 + 3, str2 + 4, 3); printf("%s\n", str1); printf("%s\n", str2);
memcmp(p1, p2, n)
比较p1和p2指向的内存中的内容是否相等,比较n个字节
int *q = malloc(4); *q = 259; int *r = malloc(4); *r = 13; int result = memcmp(q, r, 2); printf("result = %d\n", result);
定义两个整型指针,分别用malloc、calloc对其分配空间保存3个元素,malloc分配的空间用memset清零,随机对数组进行赋值随机范围1-3,赋值后用memcmp比较两个数组。如果相同打印Good!否则打印Failed...
//定义两个整型指针,分别用malloc、calloc对其分配空间保存3个元素 int *m = malloc(sizeof(int) * 3); int *n = calloc(3, sizeof(int)); //malloc分配的空间用memset清零 memset(m, 0, sizeof(int) * 3); //随机对数组进行赋值随机范围1-3 for (int i = 0; i < 3; i++) { *(m + i) = arc4random() % 3 + 1; *(n + i) = arc4random() % 3 + 1; } //打印数组m printf("\n数组m:\n"); for (int i = 0; i < 3; i++) { printf("%d ", *(m + i)); } //打印数组n printf("\n数组n:\n"); for (int i = 0; i < 3; i++) { printf("%d ", *(n + i)); } printf("\n"); //赋值后用memcmp比较两个数组 int result1 = memcmp(m, n, sizeof(int) * 3); //如果相同打印Good, 否则打印Failed if (result1 == 0) { printf("Good!"); } else { printf("Failed..."); }
- 上一篇 »{JavaScript}栈和堆内存,作用域
- 下一篇 »java中静态变量在内存中的位置