ios--c DAY_10

//
//  main.m
//  Lesson_15-8-10
//
//  Created by lanou3g on 15/8/10.
//  Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//

#import <Foundation/Foundation.h>
//static int age=12;//只能在这个文件内有效,外部文件不能访问。
int Age=19;
struct Student{
    char _name[20];
    char sex;
    int age;
};
int main(int argc, const char * argv[]) {
    //内存
    //高-->低:栈区--堆区--静态区--常量区--代码区
#pragma mark 栈区
    //===栈区:
    //  -->局部变量:函数内,循环,分支结构。
    //  -->栈区内存比较少,不用自己管,系统会自动释放但是数据还在。所以在访问数据越界的时候,会指向一个莫名的数据的原因。
    //  -->当使用函数,循环,分支中的局部变量生命周期结束之后,系统会自动销毁和回收变量存储空间,但是这个变量的值是还在。
    //  -->函数返回值属于栈区 返回栈区的内存是不安全的。
    //  -->超出内存的话,系统会崩溃。
    //  -->如果没有初始化的话,变量并不知道该去哪里。
#pragma mark 静态区
    //===静态区:
    //  -->static修饰的变量。
    //  -->全局变量:程序运行结束之后,静态区的内存被回收,生命周期同程序。
//    int num=5;//栈区
//    static int num1=9;
    //  -->静态区(局部变量):从定义的位置开始,到当前函数结束。
    //  -->静态区内存由系统自动分配和回收。
    //  -->静态变量如果没有初始值,默认为0。
    //  -->静态变量在编译时初始化,运行期间是可以改变的。
    //static:
    //        -->修饰全局变量
    //        -->修饰局部变量
#pragma mark 常量区
    //===常量区:
    //  -->内存:数字,字符,字符串等。
    //  -->常量区的存储空间由系统分配和回收的。
    //  -->程序运行接收后,回收存储空间。
    //  -->只读不能修改。
//    char *p="hello";//常量区--只能访问
    //    p0]='i';//修改是不可以的。
//    char ss[]="nihao";//数组操作的字符串在栈区的副本
#pragma mark 代码区
    //===代码区:存语句的。
    //      -->由系统分配和回收。
    //      -->程序运行结束之后由系统自动收回分配的内存。
    //      -->只能读不能修改。
#pragma mark 堆区
    //===堆区:
    //      -->由iOS工程师负责分配和回收。
    //      -->忘记回收会造成内存泄露。这个内存一直被占。其他没法使用。
    //      -->程序运行结束之后回收堆内存。如果不能及时回收堆内存的话,可能会因为内存泄露,造成堆区内存全部被占用,程序无法继续执行下去。---对应操作系统的临界资源里的死锁问题,别人申请资源,怎么也申请不到的状况。
    //      -->void *mallc(size_t)开辟空间--无类型的指针,也就是可以转换成任意类型。
    //         -->在堆区指定size_t个字节的空间,并且把空间的首地址返回。
    int *p_int=NULL;
    p_int=malloc(4);//指针p_dui指向了开辟的首地址。
    *p_int=10;//这时,10存在堆区。
    
    float *p_float=malloc(sizeof(float));
    *p_float=3.14;
    
    //分配多个连续的空间--用来存储数组元素。
    char *p_char=malloc(8);
    strcpy(p_char, "beijing");
    printf("%s\n",p_char);
    printf("\n=================================================\n");
    //分配一个随机整型数组,有10个元素,
    int *p_intArray=malloc(sizeof(int)*10);
    int arrayInt[10]={0};
    for (int i=0; i<10; i++) {
        arrayInt[i]=arc4random()%(60-30+1)+30;
    }
    p_intArray=arrayInt;//把栈区的数据赋给堆区
    for (int i=0; i<10; i++) {
        printf("%d\t",p_intArray[i]);
    }
    printf("\n=============================================\n");
    //直接给堆区内存赋值
    for (int i=0; i<10; i++) {
        *(p_intArray+i)=arc4random()%(30-10+1)+10;
        printf("%d\t",*(p_intArray+i));
    }
    printf("\n================================================\n");
    //开辟一个结构体的堆区
    struct Student *p_struct=malloc(sizeof(struct Student)*1);
    strcpy(p_struct->_name,"yibella");
    p_struct->sex='m';
    p_struct->age=22;
    printf("%s\t%c\t%d\n",p_struct->_name,p_struct->sex,p_struct->age);
    printf("\n===================================================\n");
    //开辟一个结构体数组的堆区,用结构体数组指针来接收开辟的空间的首地址
    struct Student (*p_structArray)[3]=malloc(sizeof(struct Student)*3);
    strcpy(p_structArray[0]->_name, "bella");
    strcpy(p_structArray[1]->_name, "jack");
    strcpy(p_structArray[2]->_name, "rose");
    p_structArray[0]->sex='m';
    p_structArray[1]->sex='f';
    p_structArray[2]->sex='m';
    p_structArray[0]->age=22;
    p_structArray[1]->age=23;
    p_structArray[2]->age=22;
    for (int i=0; i<3; i++) {
        printf("%s\t%c\t%d\n",p_structArray[i]->_name,p_structArray[i]->sex,p_structArray[i]->age);
    }
    printf("\n");
#pragma mark 释放开辟的堆区内存
    //void free(void *) 将指定的地址所对应的空间释放
    p_structArray=NULL;//指针指向0x0,只是把p_structArray的指向
    free((*p_structArray));
    printf("==>原本p_struct的地址:%p\n",p_struct);
    struct Student *p_structPreFree=p_struct;
    printf("还没有free掉p_struct,把p_struct赋给p_structPreFree:%s\n",p_structPreFree->_name);
    free(p_struct);//只是释放空间,内容还在,指针也还指向原来分配给它的堆地址的首地址。这个时候,这个已经释放掉的内存空间如果分配给其他变量,这时候,p_struct指针还指向这个空间,以至于会产生两个指针指向这里,这时就会出现打架状态了。
    struct Student *p_struct1=p_struct;
    strcpy(p_struct1->_name, "jack");
    strcpy(p_struct->_name, "rose");//这时的p_struct就为野指针,本来free(p_struct)是想告诉p_struct指针,自己下次不能再使用这块内存了,但是如果不把p_struct=NULL的话,下次再使用p_struct,它还是不要脸的使用这块本不该自己管理的内存,并且还去修改了这块内存的数据,这个时候,p_struct1就不满意了,p_sturct1说:p-struct你已经把这块地址给我了,你还跑来,是不是太不要脸了点。总结:这个时候的p_struct就叫做野指针,野指针说的是它指向了本不属于他的地址空间。
    //本来主人p_struct1想把自己的名字从yibella改为jack,因为他太爱jack的对爱牺牲的精神,结果那个偷渡者p_struct却不喜欢jack,把名字改成了rose,这下可好,惹怒了p_struct1,怎么办呢?
    printf("把p_struct指向的首地址给p_struct1:%s\t\t%c\t%d\n",p_struct1->_name,p_struct1->sex,p_struct1->age);
    printf("再利用p_struct来调用它指向的那块内存的内容:%s\t%c\t%d\n",p_struct->_name,p_struct->sex,p_struct->age);
    printf("==>p_struct free第一次的地址:%p\n",p_struct);
    p_struct=NULL;//把p_struct这个指针指向一个NULL,
    printf("==>把p_struct置为NULL:%p\n",p_struct);
    free(p_struct);//
    printf("==>%p\n",p_struct);
    
    //练习:把数组中的元素赋给堆区;
    int array[10]={1,2,3,4,5,6,7,8,9,10};
    int *array1=malloc(sizeof(int)*10);
    printf("==>分配给array1的地址:%p\n",array1);
    array1=array;//把指针指向array数组的首地址
    for (int i=0; i<10; i++) {
        printf("%d\t",*(array1+i));
    }
    printf("\n");
    //练习:有一个字符串,其中有数字,提取其中的数字,要求动态分配内存。
    //自己写的:
    printf("\n================================================\n");
    char string[25]="yibella520zhouyi1314";
    int count=0;
    int i=0;
    int j=0;
    char array_int[10]={0};
    while (string[i]!='\0') {
        if (string[i]>='0'&&string[i]<='9') {
            count++;
            array_int[j]=string[i];
            j++;
        }
        i++;
    }
    int count_intArray=0;
    i=0;
    printf("\n");
    while (array_int[i]!='\0') {
        count_intArray++;
        i++;
    }
    printf("\n");
    char *p_String=malloc(sizeof(int)*count_intArray);
    p_String=array_int;
    printf("放在堆区:\n");
    for (int i=0; i<count_intArray; i++) {
        printf("%d\t",*(p_String+i)-'0');//把数组字符转换成数字
    }
    printf("\n=================================================\n");
#pragma mark 自己总结数组指针和指针的问题
    //当用指针指向数组的时候,指针+1只是在point_ArrayInt的地址基础上向高位偏移一个数据类型的字节单位。
    int array_Int[3][3]={1,2,3,4,5,6,7,8,9};
    int *point_ArrayInt=array_Int;
    printf("%d\n",*(point_ArrayInt+2));
    //总结:在指针指向二维数组的时候,用指针数组就可以用pointArray_ArrayInt很快的换到下一行的首地址。为什么呢?
    int (*pointArray_ArrayInt)[3]=array_Int;
    printf("%d\n",pointArray_ArrayInt+2);
    
    char a[3][20]={"abc","bcd","asd"};
    char *r=a;
    printf("=========>%c\n",*(r+1));
    
    //练习:输入三个学员的姓名,动态分配内存 保存学员的姓名,并最后输出。
    //单用指针指向字符串数组,指针+1只是向高位偏移一个数据类型的字节单位长度--切记切记
    char _name[3][10]={0};//栈区
    printf("输入学员姓名:\n");
    for (int i=0; i<3; i++) {
        scanf("%s",_name[i]);
        getchar();
    }
    printf("\n");
    char *p_charName0=malloc(sizeof(char)*30);
    for (int i=0; i<3; i++) {
        strcpy(p_charName0+i, _name[i]);//这时的p_charName0+i只是在p_charName0指针所指向的地址的基础上向高位偏移i*sizeof(所指向的数据的类型)
    }
    for (int i=0; i<3; i++) {
        printf("%s\t",p_charName0+i);
    }
    printf("\n===============================================\n");
    //指向一维数组的指针,一定要注意当是二维数组的时候,要用数组指针来指向,不然会出问题。
    char (*p_charName)[10]=malloc(sizeof(char)*30);
    for (int i=0; i<3; i++) {
        strcpy(p_charName+i, _name[i]);
    }
    for (int i=0; i<3; i++) {
        printf("%s\t",(p_charName+i));
    }
    printf("\n==============================================\n");
#pragma mark void *calloc(要开辟的个数,要开辟的字节数)
    //void *calloc(n,size_t)
    //在堆区开辟一个n*size_t 个字节的空间,并把空间的首地址返回。同时对开辟的空间进行清零。
    //效率比malloc低。
    char *char_calloc=NULL;
    char_calloc=calloc(10, sizeof(char));
    
    strcpy(char_calloc, "hello");
    printf("%s\n",char_calloc);
    //释放
    free(char_calloc);
    char_calloc=NULL;
    
#pragma mark realloc(<#void *#>, <#size_t#>)
   // realloc(<#void *#>, <#size_t#>)
    //在给定的地址空间的基础上,如果当前指针上的空间足够大,那么将地址扩大,如果空间的地址不足,那么重新找一块新的地址按照NewSize大小分配一个空间,将原有的数据从头到尾拷贝到新的内存区域,然后释放掉原来的指针指向的内存区域。
    //!!!!**自动释放不需要手动释放
    //如果size_t的长度小于void *的长度,可能会造成内容缺失
    int *p_old=malloc(10);
    int *p_new=realloc(p_old, 21);//先看p_old的空间10,不够15,所以要重新分配空间,系统自动把p_old释放掉。
    printf("旧:%p\t新:%p\n",p_old,p_new);
    free(p_new);
    p_new=NULL;
    printf("覆盖后p_old:%p\n",p_old);
//    int *p_new1=realloc(p_old, 9);//p_old的空间10,够9,所以覆盖掉p_old。
#pragma mark memset(<#void *#>, <#int#>, <#size_t#>)
    //对内存单元的操作函数
//    memset(s, ch, n)
    //将s所指向的某一块内存中的前n 个字节的内容全部设置为ch制定的ASCII值,块的大小由打三个参数制定.
    int *intArray=malloc(20);
    for (int i=0; i<20; i++) {
        intArray[i]=i;
        printf("%d\t",intArray[i]);
    }
    printf("\n");
    memset(intArray, 0, 5);
    for (int i=0; i<20; i++) {
        printf("%d\t",intArray[i]);
    }
    printf("\n=========================================================\n");
#pragma mark 内存拷贝函数--》memcpy(void *dest, const void *src, size_t)
    //memcpy (目标指针所指向的地址的首地址, 从旧指针指向的地址的首地址开始,拷贝n个字节)
    char *p_oldname=malloc(20);
    p_oldname="yibella";
    char *p_newname=malloc(30);
    memcpy(p_newname, p_oldname, 3);
    printf("%s\n",p_newname);
    //不从起始位置拷贝,而从偏移后的开始拷贝
    memcpy(p_newname, p_oldname+2, 5);
    printf("%s\n",p_newname);
    
#pragma mark memcmp(<#const void *#>, <#const void *#>, <#size_t#>)
//    memcmp(<#const void *#>, <#const void *#>, <#size_t#>)
    //比较两个指针地址的前size_t个字节的大小。
    char  *num1="bella";
    char *num2="bell";
    int n=memcmp(num1, num2, 3);
    if (n>0) {
        printf("%s比%s大\n",num1,num2);
    }else if (n<0){
        printf("%s比%s小\n",num1,num2);
    }else{
        printf("%s跟%s一样大\n",num1,num2);
    }
    
    int aa[3]={1,2,3};
    int *pointaa[3]={NULL};
    *pointaa=aa;
    printf("%d\n",*pointaa[0]);
    
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值