今天主要讲的是内存的几个区间以及处理内存的一些函数
#import <Foundation/Foundation.h>
char *function()
{
char str[] =
}
利用关键字static 修饰的变量叫做静态变量 并且储存在静态区
特点1 :如果你不给初值 默认是0
特点2 :只初始化一次
staticint number1;// 全局静态变量
全局变量
int number2 =555;
void function()
{
staticint number = 10;// 局部静态变量
// 局部静态变量 作用域 :到下面最近的一个大括号结束
number++;
printf("%d\n",number);
}
void function1() {
int a =5;
int b =6;
printf("%d %d\n", a, b);
}
void function2()
{
int value =100;
printf("%d\n", value);
}
void function3()
{
int temp;
printf("%d\n",temp);
}
int main(int argc,const char * argv[]) {
// 内存划分为五个区域
// 分别是 栈区 堆区 静态区 常量区 代码区
// 内存地址由 高到低
// 学习目标 按顺序记住
#pragma mark -- 代码区(这个是一种注释方法这样注释可以创建一个索引)
// 电脑的存储都是以 二进制数据进行的
// 咱们写的代码 会被系统转化成二进制数据存储代码区
#pragma mark -- 常量区
// 常量区存储的常量的特点
// 常量是运行期间 不能改变的量
char *str ="zhuang";
// 把h更改成w
// 不可以更改zhuang的值但是可以更改str的值
*(str + 1) ='w';
printf("%s",str);
str = "haha";// 指针的赋值就是指针的重指向
char str[] ="zhuang";
// 数组的名字 地址数组首元素的地址 数组首元素的常量地址
// 把h更改成w
// 这种情况是把常量区的常量字符串 拷贝到栈区
str[1] ='w';
printf("%s",str);
str = "haha";// 是错的 首元素的常量地址不可更改
#pragma mark -- 静态区
// 静态区: 存储两种变量
// 1.静态变量
// 2.全局变量
// 静态区变量保存周期 : 直到你的程序运行结束静态变量才会被释放(伴你到永生)
function();
function();
#pragma mark -- 栈区
int number1 =5;
int number2 =10;
int number3 =15;
function1();
for (int n =0; n < 1000000; n++) {
function1();
}// 不管调用多少次都是频繁的进出栈 不会占用内存
//
printf("%p\n",&number1);
printf("%p\n",&number2);
printf("%p\n",&number3);
// 栈区有多大?
// 大概7M - 8M
char sr[8187 *1024] = {0};
// 出栈和入栈的规则
// 先入栈的后出栈 先入栈栈底
// 入栈(压栈)
// 出栈顺序 : 从栈顶开始出栈
// 之所以栈区 容量不是特大又不会出现崩溃的现象
// 是因为 栈区频繁的进行出栈和入栈只要一次性不把栈中间堆满 不会轻易的出现崩溃
// 定义变量的时候 切记给初值 避免出现莫名其妙的问题
function2();
function3();
#pragma mark -- 堆区
// 堆区 是程序员开辟空间是程序员释放空间
// 手动开辟空间 手动释放空间
// 堆区的空间 大概就是咱们内存的空间
// 开辟空间函数
// void *malloc(<#size_t#>)
// void *表示一个无类型的指针可以转化成任何类型的指针
// size开辟空间的大小 开辟多少字节空间
// 给整形指针p指向的位置开辟了4个字节的堆内存空间
int *p = malloc(4);
*p = 10;
printf("%d\n",*p);
// char *str = malloc(8);
// strcpy(str, "wang"); // 正确的
// strcpy(str, "wangwangwang");// 错误的 开辟了多少空间不要超过开辟的空间 如果超出了给定的空间可能会覆盖掉超出内存中你需要的值 还有超出的空间不会被释放造成内存泄漏
int *p = malloc(4);
*p = 5;
short *p2 = malloc(4);// 开辟多少空间 最好就用多少
*p2 = 10;
*(p2 + 1) =15;
// 释放空间函数
// free(<#void *#>)
// 1.标记删除不会抹去该空间存储的数据 只会把这块空间标记为可用
// 2.把指针置为空
// // 开辟空间
int *p = malloc(4);
// // 使用空间
*p = 10;
printf("%d",*p);
// // 释放空间
free(p);
p = NULL;
int *p = malloc(sizeof(int ) *5);
for (int i =0; i < 5; i++) {
*p = i + 1;
p++;
}
// 指针地址发生变化 释放本不属于你开辟的区域
// 这时候 就会崩溃
// free(p );
// 修改 把指针移回去
for (int i =0; i < 5; i++) {
p--;
}
free(p - 5);
p = NULL;
// 练习1 :有⼀字符串,其中包含数字,提取其中的数字.要求动态分配内存保存提⽰:先计算出有⼏个数字,然后根据数字的个数来开辟空间
char str[] ="122sad21d";
unsignedlong count = strlen(str);
int n =0;
for (int i =0; i < count; i++) {
if (str[i] <='9' && str[i] >= '1') {
n++;
}
}char *p = malloc(n +1);// 还有一个'/0'需要分配空间
int index =0;
for (int i =0; i < count; i++) {
if (str[i] <='9' && str[i] >= '1') {
// 进到分支里面的 肯定是数字
p[index] = str[i];
index++;
}
}
p[index] = '\0';
printf("%s",p);
free(p);
p = NULL;
// 练习2 :输⼊3个单词,动态分配内存保存学员姓名,并在最后输出
char *words[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 ",words[i]);
// 释放空间
free(words[i]);
words[i] = NULL;
}
// 其他的分配堆内存函数
// 在堆内存当中 开辟n * size个字节空间 并且把开辟的内存空间清零
// 因为有一个清零的过程 所以效率偏低
// calloc(int n, size);
int *p = calloc(3,sizeof(int));
// 重新分配函数
// realloc(<#void *#>(原来分配地址), <#size_t#>(重新分配的,新增加的新的空间大小))
// 情况1 : 如果原来分配的地址可以扩充空间 那么就在原地址扩充
// 情况2 : 如果原来分配的地址不能扩充那么系统会重新分配一个空间 并且把原来地址存储的数据拷贝到新空间里面然后系统自动释放原地址的空间
int *p_old = malloc(10);
int *p_new = realloc(p_old,15);
printf("%p\n%p",p_old,p_new);
// free(p_old); 过度释放(释放一个已经释放的空间);
free(p_new);
p_new = NULL;
// 内存操作函数
// 把开辟的空间 多少字节重置成 每个字节都重置
// memset(开辟的空间的指针, int c,字节数);
// 用途: 把开辟好的空间清零
int *p = malloc(sizeof(int) *4);
for (int n =0; n < 4; n++) {
p[n] = n + 5;
}
// 清0
memset(p, 0, sizeof(int) *4);
for (int i =0; i < 4; i++) {
printf("%d\n", p[i]);
}
// 内存拷贝函数
// 从来源 拷贝到 目的地多个字节
// memccpy(<#void *#>来源, <#const void *#>目的地, <#int#> <#size_t#>字节数);
// 内存比较函数
// 两个地址 按字节进行比较 返回第一个不同的差值
// memcmp(指针1,指针2, 字节数)
return0;
}