//
// main.m
// LessonMemory
//
// Created by laouhn on 15/7/28.
// Copyright (c) 2015年 池海涛. All rights reserved.
//
#import <Foundation/Foundation.h>
struct student {
char name[20];
char Sex;
int age;
};
typedef struct student Student;
void fun2()
{
printf("sosososososos");
}
int main(int argc, const char * argv[]) {
#pragma mark--栈区:函数参数或者是局部变量存储的区域
/*
>栈区的特点
1.分配原则:有高到底分配,由低到高存取
2.函数调用的过程就是出栈的过程.调用函数时入栈,系统会给该函数分配所需的空间;函数调用结束,出栈,系统会将分配的空间回收.
3.栈区空间是有限的 8M左右,之所以程序运行不会崩溃是因为----栈区空间在频繁的开辟以及释放
4.对于栈区空间的管理是由系统进行管理,不需要我们进行管理
int a = 10;
int b = 10;
int c = 10;
printf("a的地址 %p\nb的地址%p \nc的地址 %p\n",&a,&b,&c);
*/
#pragma mark---标记2 静态区:全局变量和静态变量存储的区域
/*
静态变量的特点:
1.静态变量只初始化一次
2.惊天变量如果不赋值,默认为0
3.静态变量空间一旦开辟,不会回收.在程序执行周期中都存在
静态区分为两部分:一部分存储赋值的全局变量和静态变量,另一部分存储没有赋初值的全局变量和静态变量
*/
//static int num = 0;//由static 修饰的变量就是静态变量,局部静态变量.
#pragma mark ----常量区
//常量区:存储常量,整型常量,浮点型常量,字符常量,字符串常量
//printf("%p\n","iOS");
//char *str = "iPhone";
//str[0] = 'a';//常量区内容是只读的,不能被修改
//printf("%s\n",str);
#pragma mark ++++变量和常量
//变量:可以被修改的量,变量相当于一个容器,容器本身不发生变化,变化的是容器中存储的内容
//常量:不可以被改变的量
//const 修饰变量,一旦变量被const修饰,变量就会当做常量来使用.
//口诀:看const修饰的是谁,const修饰谁,谁就不会发生改变,如果const修饰的内容中存在基本数据类型,将基本数据类型忽略掉
//面试题
//区分下列变量谁不会放生改变
// int a = 10;
// int b = 30;
// const int *p1 = &a;
//1.const 修饰的是*p1 *p1 = 20 是错误的 *p1 处于只读状态
// a = 39;
// printf("%d ",*p1);
// p1 = &b;
//2.const 修饰 p2,此时p2 处于只读状态,不能被重新赋值
// int *const p2 = &a;
// //p2 = &b;
// *p2 = 20;
//3.const 修饰的 p3 ,此时*p3 处于只读状态,不能被重新赋值,此时与第一种情况相同
//int const *p3 = &a;
//4.const 修饰 *p4 和p4,此时*p4 和p4都处于只读状态,都不能被重新赋值
//const int *const p4 = &a;
//char str1[] = "iPhone"; //此时,常量去得'iPhone',拷贝一份给栈区的数组str进行保存
#pragma mark ---代码区:所有的语句编译成cpu指令存储在该区域
//printf("%p\n",fun2);
#pragma mark ----堆区:由我们(iOS开发人员)自主管理的区域(手动开辟,手动释放);
//内存分配函数
//void *malloc(unsigned int size);
//void *表示是无类型的指针,可以转化为任意类型的指针.
//malloc函数的作用: 在堆区开辟指定size 个字节的空间,并把空间的首地址返回
//int *p = NULL;
//指针变量p存储的是malloc出来的 堆区4个空间的地址
// p = malloc(4);
// *p = 3;
// printf("%d\n", *p);
// char *str = malloc(8);
// printf("%p \n", str);//指针变量 str中存储的是 堆区的地址
// printf("%p \n",&str);//指针变量 str自己的地址
//char string[8200 * 1024] = {'\0'};
//iPhone 存储到该空间
// strcpy(str, "iPhone");
//strcpy(str, "Win Phone");
//该方式不合法, 因为拥有权限的空间只有 8 个字节,超出的不在字节控制范围之内
// int *a = malloc(4);
// short *b = malloc(4);
//a 分配了一块内存区域,可存放一个int 类型的数据, b 可以存放两个 short类型的数据
//printf("%s \n",str);
//
// int *p = malloc(6);
// *p = 7;
// p[1] = 5;
//*(p + 1) --p[1],不可以这样写,空间不够,指针只开辟了6个空间,而第二个元素需要4个字节占用了不合法的空间
//分配一个结构体内存
// Student *stu = malloc(sizeof(Student));
//分配一个结构体数组内存
//Student *stuArray = malloc(sizeof(Student) * 5);
//void free(void *) ;//将指定地址所对应的空间释放(还给系统);
//int *p = NULL;
// p = malloc(6);//该空间,系统找不到了,照成内存泄露
//p = malloc(10);
//free(p);//开辟之后,记得释放,如果不释放就会出现问题:内存泄露
//free(p);过度释放,照成程序崩溃
// p = NULL;//将空间释放之后,将指针置为NULL 防止野指针
// free(p); //不会报错,p 指向无效空间
//free(p);
//free(p);
//free 函数的作用是释放内存,内存释放是标记删除
//注意:释放一定要等到不使用的时候释放
//堆区内存问题:
/*
1.野指针:访问一块没有权限的空间
2.过度释放:一块空间被释放了多次,----过度释放会照成程序立即crash
3.内存泄露:空间没有释放,造成内存的堆积,不会立即crash,存在安全隐患
*/
/*
int *p = malloc(5 * sizeof(int));
for (int i = 0; i < 5; i++) {
*(p + i) = arc4random() % (40 - 20 + 1) + 20;
}
for (int i = 0 ; i < 5 - 1; i++) {
for (int j = 0; j < 5 - 1 - i; j++) {
if (*(p + j) > *(p + j + 1)) {
int temp = *(p + j);
*(p + j) = *(p + j + 1);
*(p + j + 1) = temp;
}
}
}
for (int i = 0; i < 5; i++) {
printf("%d ",*(p + i));
}
//释放 手动开辟的空间
free(p);
p = NULL;
*/
/*
int i = 0;
int k = 0;
int j = 0;
char str[] = "13s4sf3f24";
// int a[20] = {0};
char *p = NULL;
while (str[i] != '\0') {
if (str[i] >= '0' && str[i] <= '9') {
//a[k++] = str[i];
k++;
}
i++;
}
i = 0;
//分配空间,按照字符串进行处理
printf("数字个数=%d \n",k);
p = malloc((k + 1)*sizeof(int));
while (str[i] != 0) {
if (str[i] >= '0' && str[i] <= '9') {
*(p + j) = str[i];
j++;
}
i++;
}
*(p + j) = '\0'; //最后添加\0
printf("%s\n", p);
free(p);
p = NULL;
*/
//内存分配的另一个方式: calloc ---c是clear 的首字母,该函数的作用与malloc的作用,但是多了一步清零操作,该函数的执行效率比malloc低
//int *p = calloc(10,4);//第一参数代表分配空间的个数,第二个参数代表每个空间所占的字节数
//使用完,要释放
//free(p);
//防止野指针
//p = NULL;
//void *realloc(void *p,unsigned newSize);
//内存重新分配的函数,先以之前的内存空间的首地址为基准进行重新划分.如果原来空间够用,直接返回原来空间的首地址,如果原来空间不够用,就重新寻找新的空间进行划分,并返回这块空间的地址,另外,realloc 内部集成了将之前内存free的操作.
// char *p = malloc(10);
// char *p1 = realloc(p, 20);//参数1 是之前空间的首地址,参数2是重新开辟空间的大小
// printf("p的地址是:%p\np1的地址是:%p",p,p1);
//内存操作函数
//----memset(void *,int,size_t),为malloc分配的空间执行清理操作,参数1代表从哪个位置开始清理,参数2代表清理时使用什么值代替,参数3代表清理多大的空间
// char *p = malloc(3);
// memset(p, 0, 3);//从p的位置开始清理,清理3个字节,把每个字节上值赋值为0
// free(p);
// p = NULL;
//
//----memcpy(void *dest,const void *source, size_t); 从source指向的内存开始 拷贝 size 个字节大小,到dest 指向的内存.
// char str[] = "ZZS1570732";
// char string[] = "KONGKONG";
// memcpy(str, string, 4);
// printf("%s\n%s",str,string);
//int memcmp(const void *buf1,const void * buf2,unsigned int count);从给定得两个地址buf1,buf2,从开始进行比较,比较count个字节返回第一个不相等的字节空间的差值.
//定义两个 整型指针,分别用malloc、calloc对其分配空间保存3个元素,malloc分配的空间用memset清零,随机对数组进行 赋值 随机范围1-3,赋值后用memcmp比较两个数组。如果相同打印Good!否则打印Failed...
int *p = malloc(3 * sizeof(int));
int *p2 = calloc(3, 4);
printf("%d",*p);
printf("%d",*p2);
memset(p, 0, 12);
for (int i = 0; i < 3; i++) {
p[i] = arc4random() % (3 - 1 + 1) + 1;
p2[i] = arc4random() % (3 - 1 + 1) + 1;
printf("%d %d \n",p[i],p2[i]);
}
//比较
int result = memcmp(p,p2 , 12);
if (result == 0) {
printf("GOOD!");
}else
printf("BAD!");
free(p);
free(p2);
p = NULL;
p2 = NULL;
return 0;
}
//释放