C 入门 第十节 存储区
int b = 5; // 存放在静态区 作用域是所有文件
// 代码区
void testMemory()
{
printf("代码区\n");
}
//static int b1 = 8; //作用域所有文件
int main(int argc, const char * argv[]) {
/*
在计算机的内存中,可以分为5个区,每个区都有各自的操作以及管理内存的方式
栈,堆,静态(全局),常量,代码区是按照内存笛子从小到大分配的
代码区;
// 打印各个存储区区域
// 栈区:
int a = 3;
// 堆区:
int *p = malloc(10);
// 静态(全局):
static int b = 5;
// 常量:
char *s = "iphone";
// 函数存储在代码区:
printf("栈区:%p\n",&a);
printf("堆区:%p\n",p);
printf("静态:%p\n",&b);
printf("常量:%p\n",s);
printf("代码:%p\n",testMemory);
*/
#pragma mark -----------栈区:函数参数或者是局部变量存储的区域----------
/*
栈区内存
1 . 局部变量的存储空间,基本都在栈区,局部变量在函数,循环,分支中定义.
2 . 栈区的存储空由高到低分配,从低到高存储.
3 . 栈区内存由系统负责分配和回收,开发者没有管理的权限.定义局部变量时由系统分配存储空间,局部变量被销毁时由系统回收存储空间,但是存储空间中的数据没有被清空
4 . 当函数,循环,分支执行结束后,局部变量的生命周期结束,不能在被使用,由系统销毁并回收存储空间.
5 . 栈底,栈顶. 栈底是栈区的起始位置,先定义的变量所占用的内存从靠近栈底开始分配;后定义的变量所占的内存逐渐向栈顶分配.
6 . 入栈,出栈. 入栈: 定义新的局部变量,分配存储空间;出栈: 局部变量被销毁,存储空间被收回
7 . 栈的特点: 先进后出,后进先出;
8 . 栈区会存在安全问题: 在函数中返回栈内存是不安全的
*/
// int a = 10;
// char b = 'a';
// double c = 3.4;
// printf("a的地址: %p\n",&a);
// printf("b的地址: %p\n",&b);
// printf("c的地址: %p\n",&c);
//
/*
常量区
1 . 常量存储在常量区. 常量 字符串等等
2 . 常量区存储空间是由系统分配和回收
3 . 程序运行结束后,常量区的存储空间被收回
4 . 常量区的数据只能被读取,不能被修改.修改会造成崩溃
*/
#pragma mark -------静态区: 全局变量和静态变量存储的区域-----------
/*
静态区
1. 全局变量,使用static修饰的局部变量,都存储在静态区.
2. 静态区的存储空间由系统分配和回收.
3. 程序运行结束后,静态区的存储空间被回收.静态区变量的生命周期跟程序一样长.
4. 静态变量只能初始化一次,在编译时进行初始化,运行期可以修改
5. 静态变量如果没有实质初始化,默认值为0;
*/
// static int b1 = 8; //静态变量,作用域是本文件
#pragma mark ---------代码区: 所有语句编译的cpu指令存储的区域--------------------
/*
代码区
1. 由系统分配和回收
2. 程序结束后,由系统回收分配过的存储空间
3. 只能读,不能改
*/
#pragma mark ---堆区: 由我们(ios开发工程师)自主管理的区域(手动开辟,手动释放)--------
/*
堆区
1. 由开发者负责分配和回收
2. 忘记回收内存会造成内存泄露
3. 程序结束后会回收堆区内存,但是如果不能及时回收堆内存,程序运行期间可能会因为内存泄露造成堆内存被全部占用,程序无法运行.
内存分配函数
void *malloc(size)
void * 表示的是无类型指针,可以转换任意类型指针.
函数的作用: 在对区开辟指定size个字节的空间,并把空间的首地址返回
int *p = NULL;
p = malloc(sizeof(int));
*p = 4;
printf("%d \n",*p);
float *r = NULL;
r = malloc(sizeof(float));
*r = 8;
printf("%.2f ",*r);
// 分配存储空间存储数组元素,即分配多个连续的存储空间
// 练习: 分配1个字符数组的内存,8个元素 "iPhone"
char *p = malloc(sizeof(char) * 8);
strcpy(p, "iphone");
printf("%s ",p);
// 练习: 分配一个整型的数组,10个元素,随机产生10个30~60之间的数,存储在分配的内存空间
int *p = malloc(sizeof(int) *10);
for (int i = 0; i < 10; i ++)
{
*(p+i) = arc4random()%(60 - 30 + 1) + 30;
}
for (int i = 0; i < 10; i ++)
{
printf("%d ",*(p+i));
}
printf("\n");
typedef struct student
{
char name[20];
int age;
}Student;
Student *p12 = malloc(sizeof(Student));
strcpy(p12 -> name, "zhangsan");
p12 -> age = 18;
printf("%s %d\n",p12 ->name,p12 -> age);
释放开辟的空间
// void free(void *); 将指定的地址所对应的空间释放
int *r = NULL;
r = malloc(sizeof(int)); //这一块开辟的内存找不到,造成内存泄露
r = malloc(sizeof(int));
*r = 10;
free(r); //开辟空间记得区释放,如果不释放,会出现内存问题:内存泄露
r = NULL; //当空间回收之后,将指针置为null 安全,避免出现野指针,野指针: 指针指向不属于自己控制的存储单元
free(r); //内存问题: 过度释放
// void *calloc(int n,size_t size); 在堆区开辟n*size个字节空间,并把空间地址返回,该函数会将空间进行清0操作,在效率上比malloc低
char *str = NULL;
str = (char*)calloc(10, sizeof(char));
strcpy(str, "hello");
printf("string is : %s\n",str);
free(str);
str = NULL;
*/
/*
void *realloc(void*p,size_t newSize ); //在给定的地址空间上,如果当前指针空间足够,那么将他地址扩大,如果空间不足,那么重新找一块新的地址按照newSize大小分配空间.将原有数据从头到尾拷贝到新分配的内存区域,然后自动释放原来指针指向的内存区域,不需要free
int *p_old = malloc(10);
int *p_new = realloc(p_old, 150);
printf("%p %p\n",p_old,p_new);
// 如果返回的地址和新地址不一样,那么系统会将原来的地址进行一次free,对于realloc()操作,只需要释放我们新的地址空间即可
// free(p_old);//过度释放
free(p_new);
// void *memset(void *p,int c,size_t size) 从给定的地址开始size个字节直接重置为c,注意:该函数以字节单位进行操作.注要作用于清0.
for (int i = 0; i < 3; i ++)
{
array[i] = i;
printf("%d \n",array[i]);
}
//全置为0
memset(array, 0, 12);
printf("\n");
for (int i = 0; i < 3; i ++)
{
printf("%d ",array[i]);
}
printf("\n");
char *p11 = malloc(10);
memset(p11, 'a', 10);
for (int i = 0; i < 10; i ++)
{
printf("%c ",p11[i]);
}
printf("\n");
// int memcmp(void *p,void *q,size_t Count); 从给定的俩个地址p和q开始比较count个字节,返回第一个不相等字节空间的差值
int num1[3] = {1,2,3};
int num2[3] = {1,2,2};
int result = memcmp(num1, num2, 9); // 9 : 比较的字节数
printf("%d \n",result);
*/
// void *memcpy(void *p, void *q, size_t n); 从指定的scorce指向的地址向dest指向的地址单元拷贝n个字节
char wrongName[] = "bjs141148";
char rightName[] = "15";
memcpy(wrongName, "B", 1);
memcpy(wrongName + 3, rightName, 2);
printf("%s \n",wrongName);