OC学习笔记之类004指针、结构体、块

1.指针变量及基本用法
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int a=100;
        int* point;
        point=&a;
        NSLog(@"%p",point);//输出0x7ffeefbff5ac,为什么总是这个地址
        NSLog(@"%d",*point);//把值取出        
    }
}

输出
2020-05-14 17:25:43.195622+0800 EX003[866:27684] 0x7ffeefbff5ac
2020-05-14 17:25:43.195895+0800 EX003[866:27684] 100

2.指针变量作为函数参数
#import <Foundation/Foundation.h>

void swap(int* p1,int* p2){
    int temp=*p1;
    *p1=*p2;
    *p2=temp;//这里只传了值,并没有传地址
    
    p1=p2=nil;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int a=5;
        int b=10;
        NSLog(@"交换前a的值为:%d,b的值为:%d",a,b);
        NSLog(@"交换前a的指针为%p,b的指针为%p",&a,&b);

        int* pa=&a;
        int* pb=&b;
        
        swap(pa, pb);
        NSLog(@"交换后a的值为:%d,b的值为:%d",a,b);     
        NSLog(@"交换后pa的指针为%p,pb的指针为%p",pa,pb);
        
    }
}

输出:
2020-05-14 19:56:59.761501+0800 EX003[1279:65154] 交换前a的值为:5,b的值为:10
2020-05-14 19:56:59.761803+0800 EX003[1279:65154] 交换前a的指针为0x7ffeefbff5ac,b的指针为0x7ffeefbff5a8
2020-05-14 19:56:59.761835+0800 EX003[1279:65154] 交换后a的值为:10,b的值为:5
2020-05-14 19:56:59.761859+0800 EX003[1279:65154] 交换后pa的指针为0x7ffeefbff5ac,pb的指针为0x7ffeefbff5a8

3.指向数组的指针变量
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int myarray[]={1,2,3,4,5};
        int* parray1=&myarray[0];
        int* parray2=myarray;
        
        NSLog(@"指向的指针为%p",parray1);//首元素地址和数组名指向同一个地址
        NSLog(@"指向的指针为%p",parray2);

    }
}

输出:
2020-05-14 20:34:44.551895+0800 EX003[1437:75287] 指向的指针为0x7ffeefbff5a0
2020-05-14 20:34:44.552200+0800 EX003[1437:75287] 指向的指针为0x7ffeefbff5a0

4.指针运算
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int myarray[]={1,2,3,4,5};
        int* parray1=&myarray[0];
        int* parray2=myarray;
        
        NSLog(@"指向的指针为%p",parray1);//首元素地址和数组名指向同一个地址
        NSLog(@"指向的指针为%p",parray2);
        NSLog(@"--------");
        NSLog(@"数组首元素%d",*parray1);
        parray1+=2;
        NSLog(@"数组指针+2后为%d",*parray1);

    }
}

输出
2020-05-14 21:23:43.164989+0800 EX003[1519:88016] 指向的指针为0x7ffeefbff5a0
2020-05-14 21:23:43.165291+0800 EX003[1519:88016] 指向的指针为0x7ffeefbff5a0
2020-05-14 21:23:43.165321+0800 EX003[1519:88016] --------
2020-05-14 21:23:43.165346+0800 EX003[1519:88016] 数组首元素1
2020-05-14 21:23:43.165369+0800 EX003[1519:88016] 数组指针+2后为3

5.指针运算,使用指针遍历数组
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int myarray[]={1,2,3,4,5};
        
        for (int i=0,length=sizeof(myarray)/sizeof(myarray[0]); i<length; i++) {
            NSLog(@"%d",*(myarray+i));//通过指针加法来访问数组
        }
        
        NSLog(@"------");
        
        for (int* p=myarray,length=sizeof(myarray)/sizeof(myarray[0]); p<myarray+length; p++) {
            NSLog(@"%d",*p);//通过指针来访问数组
        }

    }
}

输出:
2020-05-14 21:53:54.085506+0800 EX003[1584:96489] 1
2020-05-14 21:53:54.085783+0800 EX003[1584:96489] 2
2020-05-14 21:53:54.085810+0800 EX003[1584:96489] 3
2020-05-14 21:53:54.085829+0800 EX003[1584:96489] 4
2020-05-14 21:53:54.085845+0800 EX003[1584:96489] 5
2020-05-14 21:53:54.085863+0800 EX003[1584:96489] ------
2020-05-14 21:53:54.085879+0800 EX003[1584:96489] 1
2020-05-14 21:53:54.085895+0800 EX003[1584:96489] 2
2020-05-14 21:53:54.085911+0800 EX003[1584:96489] 3
2020-05-14 21:53:54.085927+0800 EX003[1584:96489] 4
2020-05-14 21:53:54.085969+0800 EX003[1584:96489] 5

6.指向多维数组的指针变量
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        float arr[3][4]={
            {1.2,3.4,4.5,6.1},
            {7,3,4,8},
            {3,9,2,1}
        };
        
        
        for (float* p=arr[0]; p<arr[0]+12; p++) {//指针指向数组的第一维的指针,从这个地址向下移动12个元素(3*4)
            if ((p-arr[0])%4==0) {//p地址递增之后,根据移动的距离每4个元素换个行
                printf("\n");
            }
            printf("%.1f,  ",*p);
        }
        
    }
}

输出
1.2, 3.4, 4.5, 6.1,
7.0, 3.0, 4.0, 8.0,
3.0, 9.0, 2.0, 1.0,

7.使用字符指针表示字符串
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        char* str="hello world!";
        NSLog(@"%s",str);
        str+=7;
        NSLog(@"%s",str);
    }
}
8.字符指针作为函数参数
#import <Foundation/Foundation.h>
void copyString(char* to,char* from){
    while(*from){//如果from指针指向的字符部位\0
        *(to++)=*(from++);
    }
    *to='\0';
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        char* str="C语言的字符串在底层";
        char* receive[100];
        
        copyString(receive, str);
        NSLog(@"%s",receive);
        copyString(receive, "由于指针变量支持加法运算");
        NSLog(@"%s",receive);
    
    }
}

输出:
2020-05-14 23:35:19.577413+0800 EX003[1994:136273] C语言的字符串在底层
2020-05-14 23:35:19.577734+0800 EX003[1994:136273] 由于指针变量支持加法运算

9.用函数指针变量调用函数

C语言允许使用一个指针变量来指向概函数
1、定义函数指针变量的语法格式为:
函数返回值类型(*指针变量名)()
2、将任何已有的函数赋值给函数指针变量
fnPt=avg
3、使用函数指针变量来调用函数。
(*函数指针变量)(参数)

#import <Foundation/Foundation.h>
int max(int* data,int lenght){
    int max=*data;
    for (int* p=data; p<data+lenght; p++) {
        if(*p>max){
            max=*p;
        }
    }
    return max;
}

int aver(int* data,int length){
    int sum=0;
    for (int* p=data; p<data+length; p++) {
        sum+=*p;
    }
    return sum/length;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int data[]={1,3,56,788,3,32,23,54,345};
        //定义指向函数的指针变量,fnpt,并将max函数的入口赋值给fnPt
        int (*fnpt)()=max;
        NSLog(@"最大值为:%d",(*fnpt)(data,9));//这里数组名就是指针
        
        //将averg函数如克直接赋值给fnpt函数指针
        fnpt=aver;
        NSLog(@"平均值为:%d",(*fnpt)(data,9));
    
    }
}

输出
2020-05-15 00:31:52.625729+0800 EX003[2107:154882] 最大值为:788
2020-05-15 00:31:52.626052+0800 EX003[2107:154882] 平均值为:145

10.用函数指针变量作为函数参数
#import <Foundation/Foundation.h>
void map(int* data,int length,int (*fn)()){
    for (int* p=data; p<data+length; p++) {
        printf("%d, ",(*fn)(*p));
    }
    printf("\n");
}
int nochange(int val){
    return val;
}
int square(int val){
    return val*val;
}
int cube(int val){
    return val*val*val;
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int data[]={1,3,5,7,3,32,23,54,45};
        //三次调用map函数,传入三个不同的函数进去
        map(data,9,nochange);
        map(data,9,square);
        map(data,9,cube);

    }
}

输出:
1, 3, 5, 7, 3, 32, 23, 54, 45,
1, 9, 25, 49, 9, 1024, 529, 2916, 2025,
1, 27, 125, 343, 27, 32768, 12167, 157464, 91125,

11.返回指针的函数

为了保证返回的指针指向被调用函数中的局部变量,该局部变量应该使用static修饰,或者指向main函数中的变量

#import <Foundation/Foundation.h>
#define LENGTH 9
int* map(int* data,int length,int (*fn)()){
    static int result[LENGTH];//使用的是静态的数组
    int i=0;
    for (int* p=data; p<data+length; p++) {
        result[i++]=(*fn)(*p);
    }
    printf("\n");
    return result;
}
int nochange(int val){
    return val;
}
int square(int val){
    return val*val;
}
int cube(int val){
    return val*val*val;
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int data[]={1,3,5,7,3,32,23,54,45};
        //三次调用map函数,传入三个不同的函数进去,并返回三个数组
        int* arry1=map(data,9,nochange);
        for (int i=0; i<LENGTH; i++) {
            printf("%d, ",*(arry1+i));
        }
        int* arry2=map(data,9,square);
        for (int i=0; i<LENGTH; i++) {
            printf("%d, ",*(arry2+i));
        }
        int* arry3=map(data,9,cube);
        for (int i=0; i<LENGTH; i++) {
            printf("%d, ",*(arry3+i));
        }

    }
}

输出:
1, 3, 5, 7, 3, 32, 23, 54, 45,
1, 9, 25, 49, 9, 1024, 529, 2916, 2025,
1, 27, 125, 343, 27, 32768, 12167, 157464, 91125,

12.指针数组与main()函数形参与指向指针变量的指针

指针数组(数组元素用存放指针变量的数组)声明格式:
类型* 数组变量名[长度]

指向指针的指针格式为:
类型 ** 变量名如
int ** pt=&p
反过来,取出指向指针的指针的值,则需要两个**来获得真实的值

#import <Foundation/Foundation.h>
void dowork(int* age[],int len){
    for (int i=0; i<len; i++) {
        printf("指针:%p----元素值%d\n",age+i,**(age+i));
    }
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int* age[5];
        int a[]={1,2,3,4,5};
        for (int i=0; i<5; i++) {
            age[i]=&a[i];
        }
        dowork(age, 5);

    }
}

输出
指针:0x7ffeefbff590----元素值1
指针:0x7ffeefbff598----元素值2
指针:0x7ffeefbff5a0----元素值3
指针:0x7ffeefbff5a8----元素值4
指针:0x7ffeefbff5b0----元素值5

13.结构体的定义及使用(一种简化的类)

格式:
struct 结构体类型名
{
//成员列表
}

struct Person{
            NSString *name;
            int age;
 };
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        struct Person{
            NSString *name;
            int age;
        };
        
        struct Person zhangsan;
        
        zhangsan.name=@"张三";
        zhangsan.age=34;
        
        NSLog(@"%@",zhangsan.name);
        NSLog(@"%d",zhangsan.age);
        
    }
}

输出
2020-05-15 10:31:44.697597+0800 EX003[811:20383] 张三
2020-05-15 10:31:44.697873+0800 EX003[811:20383] 34

14.使用预编译指令将结构体的使用简化
#import <Foundation/Foundation.h>
#define PERSON struct Person
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        struct Person{
            NSString *name;
            int age;
        };
        
        PERSON zhangsan;//通过预编译来写
        
        zhangsan.name=@"张三";
        zhangsan.age=34;
        
        NSLog(@"%@",zhangsan.name);
        NSLog(@"%d",zhangsan.age);
        
    }
}
15.同时定义结构体及声明变量

格式:
struct 结构体名{
//成员变量
} 结构体变量名1,结构体变量名2;

#import <Foundation/Foundation.h>
#define PERSON struct Person
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        struct Person{
            NSString *name;
            int age;
        } zhangsan;
        
        zhangsan.name=@"张三";
        zhangsan.age=34;
        PERSON lisi={@"李四",43};//只有在声明结构体变量时可以使用这种方式初始化,声明过后只能单个成员初始化
        
        NSLog(@"%@",zhangsan.name);
        NSLog(@"%d",zhangsan.age);
        NSLog(@"----");
        NSLog(@"%@",lisi.name);
        NSLog(@"%d",lisi.age);
        
    }
}

输出
2020-05-15 11:25:41.308957+0800 EX003[1075:40662] 张三
2020-05-15 11:25:41.309229+0800 EX003[1075:40662] 34
2020-05-15 11:25:41.309257+0800 EX003[1075:40662] ----
2020-05-15 11:25:41.309283+0800 EX003[1075:40662] 李四
2020-05-15 11:25:41.309304+0800 EX003[1075:40662] 43

16.结构体数组
#import <Foundation/Foundation.h>
#define PERSON struct Person
int main(int argc, const char * argv[]) {
  @autoreleasepool {
    struct Person{
      NSString *name;
      int age;
    };
    
    PERSON persons[]={
      {@"张三",34},
      {@"李四",23},
      {@"王二",44}
    };
    
    for (int i=0; i<3; i++) {
      NSLog(@"%@---%d",persons[i].name,persons[i].age);
    }

  }
}

输出
2020-05-15 14:18:49.040563+0800 EX003[2707:109076] 张三—34
2020-05-15 14:18:49.040900+0800 EX003[2707:109076] 李四—23
2020-05-15 14:18:49.040932+0800 EX003[2707:109076] 王二—44

17.定义及使用块(类似于匿名函数)

定义块的语法

^[块返回值类型](形参类型1   形参1,形参类型2   形参2

定义块变量

块返回值类型 (^块变量名)(形参类型1,形参类型2

定义块变量时,无须声明形参名,只要指定形参类型即可,无需形参则使用void

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
  @autoreleasepool {
    //定义不带参、无返回值的块
    void (^printStr)(void)=^(void){
      NSLog(@"调用快的语法与调用函数完全相同");
    };
    printStr();
    
    //定义带参、返回值的块
    double (^printDouble)(double,double)=^(double width,double height){
      
      return width*height;
    };
    NSLog(@"%g",printDouble(15.34,34.32)) ;
    
    //定义快变量,再将块赋值给指定的快变量
    void (^printStr2)(NSString *);
    printStr2=^(NSString *info){
      NSLog(@"%@",info);
    };
    
    printStr2(@"块可以访问程序中局部变量的值");
 
  }
}

输出:
2020-05-15 15:26:40.796611+0800 EX003[3569:144410] 调用快的语法与调用函数完全相同
2020-05-15 15:26:40.796906+0800 EX003[3569:144410] 526.469
2020-05-15 15:26:40.796972+0800 EX003[3569:144410] 块可以访问程序中局部变量的值

18.块与局部变量
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
  @autoreleasepool {
    int my=20;
    void (^printMy)(void)=^(void){//块已经捕获了局部变脸my
      //my=30;//不可以对局部变量赋值
      NSLog(@"%d",my);
    };
    my=45;//这里即便改变了局部变量my,但是之前已经被捕获了,这次修改并不影响后面块的调用
    printMy();
    
  }
}

输出:
20

如果希望不被捕获,则需要将该局部变量前加上__block(这里是双下划线)

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
  @autoreleasepool {
    __block int my=20;
    void (^printMy)(void)=^(void){//块已经捕获了局部变脸my
      //运行时访问,获取局部变量的值,此处输出45
      NSLog(@"%d",my);
      //尝试对局部变量赋值时可以的
      my=30;
      NSLog(@"%d",my);
    };
    my=45;//这里即便改变了局部变量my,但是之前已经被捕获了,这次修改并不影响后面块的调用
    printMy();
    
  }
}

输出
2020-05-15 16:22:15.762446+0800 EX003[4183:169913] 45
2020-05-15 16:22:15.762751+0800 EX003[4183:169913] 30

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值