[TwistedFate]程序存储区划分、动态申请内存、内存操作函数
2015-10-21 20:13
323 查看
内存区划分
内存区划分为5个区:栈区 堆区(程序员管理) 静态区 常量区 代码区内存地址: 内存地址大 ———-> 内存地址小
代码区
电脑的存储都是以二进制数据存储的 书写的代码 会被系统转化为二进制数据 存储在代码区
常量区
常量区存储常量的特点: 常量是程序运行期间 不能改变量
char *str =":"; // 把h更改成w // *(str + 1) = 'w'; // 运行崩溃 // 指针的赋值是指针的重指向(没有改变常量的值) str = "haha";
char str[] = "zhuang"; // 数组名字 地址 数组首元素的地址 // 数组首元素的常量地址 // 把h 更改成 w // 是把常量区的常量字符串拷贝到栈区 str[1] = 'w'; // str = "haha" 错误 不能更改
静态区
静态区存储两种变量 (1)静态变量: 利用关键字 static 修饰的变量 叫做静态变量 并且存储在静态区 `static int number1;` 特点:1.如果初始化不赋值,默认是0; 2.只初始化一次 举例比较:
void function() { static int num = 10; num++ printf("%d ",num); } // 输出三次结果为:11 12 13 void function1() int num1 = 10; num1++; printf("%d ",num1); // 输出结果三次为:11 11 11
(2)全局变量
静态区变量 保存周期:直到你的程序运行结束,静态变量才会被释放
栈区
栈区大概7M - 8M出栈与入栈的规则:先入栈——>栈底, 再出栈
入栈:又称压栈
之所以栈区 容量不是特别大又不会出现崩溃的现象 是因为 栈区频繁的进行出栈入栈 只要一次性不把栈空间堆满 不会轻易的出现崩溃
注意:定义变量的时候 切记给初值 避免出现莫名其妙的问题
堆区
堆区 是程序员开辟空间 是程序员释放空间手动开辟空间 手动释放空间
堆区的空间 大概就是全部存储空间
开辟空间函数
void *malloc(字节大小) void * 表示无类型指针 开辟了四个字节的堆内存空间
// 给整型指针p指向的位置 开辟了四个字节的堆内存空间 int *p = malloc(4); *p = 10; printf("%d \n",*p); char *str = malloc(8); strcpy(str, "wang"); // 正确 stpcpy(str, "wangwangwang"); //错误的,开辟了多少空间 不要超过开辟的空间 printf("%s\n",str); int *p1 = malloc(4); *p1 = 5; short *p2 = malloc(4); // 开辟多少空间 最好用多少 *p2 = 10; *(p2 + 1) = 15;
释放空间函数
free(void *) 1.标记删除 不会抹去该空间存储的数据 只会把这块空间标记为可用 2.把指针置空
// 开辟空间 int *p = malloc(4); // 使用空间 *p = 10; printf("%d\n",*p); // 释放空间 free(p); p = NULL;
// 改错
int *p = malloc(sizeof(int) * 5); for(int i = 0;i < 5;i++) { *p = i + 1; p++; } free(p); // 指针发生了变化 释放了本不属于你的开辟区域 就会崩溃 // 修改 把指针改回去 free(p - 5); p = NULL;
/** 练习
* 有⼀字符串,其中包含数字,提取其中的数字.要求动态分配内存保存
提⽰: 先计算出有⼏个数字,然后根据数字的个数来开辟空间
*/
char str[] = "dsad123dsa23"; int count = 0; for(int i = 0;i < strlen(str);i++) { if(str[i] >= '0' && str[i] <= '9' ) { count++; } } // 开辟空间 char *strValue = malloc(count + 1); //加1是因为字符串有个'\0' // 记录数字该放的位置 int index = 0; for(int i = 0; i < strlen(str);i++) { if(str[i] >= '0' && str[i] <= '9') { strValue[idnex] = str[i]; index++; } } // 加上'\0' strValue[index] = '\0'; printf("%s",strValue); // 释放空间 free(strValue); strValue = NULL;
/** 练习2:
* 输⼊3个学员的姓名,动态分配内存保存学员姓名,并在最后输出
*/
char *word[3] = {0}; char str[] = {0}; for(int i = 0;i < 3;i++) { printf("请输入一个字符:\n"); scanf("%s",str); // 开辟空间 words[i] = malloc(strlen(str) + 1); // 保存字符串 strcpy(words[i], str); } for (int i = 0; i < 3; i++) { printf("%s\n",words[i]); // 释放空间 free(words[i]); words[i] = NULL; }
其他分配函数
在堆内存中 开辟 n * size 个空间 并且把开辟的空间清零 因为有一个清零的过程 所以效率偏低// calloc(int n, size)
int *p = calloc(3, sizeof(int)); free(p); p = NULL;
重新分配函数 realloc
realloc(原分配地址,新空间大小)
两种情况:
情况1:如果原来分配的地址 可以扩充空间 那么就在原来的地址扩充
情况2:如果原来分配的地址 不能扩充了 那么系统会重新分配一个空间 并且把原来的地址存储的数据拷贝到新空间 然后系统自动释放原地址的空间
int *p_old = malloc(10); int *p_new = realloc(p_old, 25); printf("%p %p\n",p_old,p_new); // free(p_old); // 过度释放 free(p_new); p_new = NULL;
内存操作函数
// 把开辟的空间 多少字节 重置成 c// memset(开辟的空间的指针, int c, 字节)
// 用途:把开辟好的空间 清零
int *p = malloc(sizeof(int) * 4); for (int i = 0; i < 4; i++) { p[i] = i + 5; } // 清零 memset(p, 0, 16); for (int i = 0; i < 4; i++) { printf("%d ",p[i]); }
// 从来源拷贝到目的地 多少个字节
// memcpy(目的地,来源 , 字节数)
char str1[] = “wanglong”;
char str2[] = “44”;
memcpy(str1, “W”,1);
memcpy(str1 + 3, str2, 2);
printf(“%s”,str1);
// 比较函数 // 两个地址 按字节 进行比较返回第一个不同的差值 // memcmp(指针1, 指针2, 字节数)
相关文章推荐
- OC学习笔记之NSString常见处理方法
- Greedy:Protecting the Flowers(POJ 3262)
- 手脱tElock 0.98b1 -> tE!
- 从date中获取相应信息
- 编译maxscale
- Codevs 玛丽卡
- MySql建表与索引
- popupWindow的使用
- WebView注入Javascript的版本兼容问题
- shell脚本批量调用git命令
- Nosql释义
- OC学习笔记之NSString
- 二叉树的先中后序遍历
- iOS 企业证书发布app 流程
- IOS构建XMPP开发
- Subject Alternative Names
- 关于架构的读书笔记
- mysql 导出慢
- Oracle一个中文汉字占用几个字节
- d3 学习参考