zoukankan      html  css  js  c++  java
  • ios学习之旅---指针也不难

    1、认识指针
    #include <stdio.h>
    //基本数据类型作为函数參数传递是值传递
    //void moveFront(int x ,int y)
    //{
    //    x  = x + 2;
    //}
    void test()
    {
        //  确定当前坐标
        int x = 20;
        int y = 150;
        printf("%p
    ",&x);
        printf("%lu
    ",&x);
    
        *((int *)(0x7fff5fbff76c)) = 22;
        printf("(%d,%d)
    ",x,y);
        //    moveFront(x, y);
        //    printf("(%d,%d)
    ",x,y);
    
    }
    
    //假设你想訪问指针所指向存储空间,就必须使用訪问指针所指向的存储空间的操作符
    void moveFront(int *x ,int *y)
    {
    //  x  = x + 2;//此时是改变指针的指向,而不是訪问指针所指向的存储空间
        *x  = *x + 2;
    }
    
    int main(int argc, const char * argv[]) {
    
        //  确定当前坐标
        int x = 20;
        int y = 150;
        printf("(%d,%d)
    ",x,y);
        moveFront(&x, &y);
        printf("(%d,%d)
    ",x,y);
    
        return 0;
    }
    


    2、指针的定义与初始化(重点掌握)


       内存中最小的存储单元:字节,每个字节在内存中都有一个编号,这编号就是指针
     
      指针:内存地址
      有了指针你就有了打开这块内存钥匙,就能够操作这一块内存
     
      指针变量:存放内存地址的变量
      定义指针:指针所指向数据类型  * 指针变量名称;
     在的定义变量时候,*是一个类型说明符,说明定义这个变量是一个指针变量
      在不是定义的变量的时候。*是一个操作符,訪问(读、写)指针所指向的那块存储空
        指针的初始化:
      
        注意点:
        1、仅仅有定义没有初始化指针里面是一个垃圾值,这时候我们成为这个指针为野指针
        2、假设操作一个野指针
           2.1 程序崩溃
           2.2 訪问不该你訪问存储。操作潜在逻辑错误
        3、不能够使用整形常量赋值一个指针变量
           由于内存是操作系统分配我们的,不是我们随便取的
        4、什么类型的指针,仅仅指向什么类型的变量
        5、多个指针能够指向同一变量
        6、指针的指向是能够改变的


    #include <stdio.h>
    
    
    //指针的定义
    void test()
    {
        int num = 10;
        
        //  定义一个指针变量
        int *p;
        p = #
        
        *p = 20;
        printf("num = %d
    ",num);
    }
    
    int main(int argc, const char * argv[]) {
    
    
    // 先定义在进行初始化
        int num = 10;
    //  定义一个指针变量p
        int * p;
        
    //    *p = # // p 还有进行初始,不可以訪问它所指向存储空间
        p = #//p 指向 num
        *p = 20;
        
        
    //  定义指针变量的同一时候进行初始
        
        int num2 = 20;
    
        int *p2 = &num2;
        
        *p2 = 40;
        
        printf("%d,%d
    ",num2,*p2);
        
    // 不可以使用整形常量赋值一个指针变量
    // 由于内存是操作系统分配我们的,不是我们随便取的
        
    //    int *p3 = 100000;//此处是错误的
    //    
    //    *p3 = 10;
        
        p2 = #
        
        printf("%p
    ",p2);
        
        char c = 'a';
        
        int *pc = &c;
        
        *pc = 10;
        
        printf("%p
    ",p2);
        
        
        return 0;
    }

    3、多级指针


    通过指针訪问变量称为间接訪问。

    因为指针变量直接指向变量,所以称为“一级指针”。


    假设通过指向指针的指针变量来訪问变量则构成“二级指针”。

    #include <stdio.h>
    
    void test()
    {
        int num = 10;
        
        int *p = #
        
        //  定义一个指针来指向变量p
        //  pp就是一个二级指针
        int **pp = &p;
        
        **pp = 30;
        printf("%d
    ",num);
        
        int ***ppp = &pp;
        ***ppp = 50;
        printf("%d
    ",num);
        
        //  四级指针
        int ****pppp = &ppp;
        ****pppp = 100;
        printf("%d
    ",num);   
    }
    void readFile(char **error)
    {
        *error = "读取错误";   
    }
    
    int main(int argc, const char * argv[]) {
      
    //    char error[100];
        
        char *error;
        
        readFile(&error);
        
        printf("%s",error);
        
        return 0;
    }

    4、指针为什么要区分类型

       1、变量的地址是变量所在占存储空间的首地址
       2、指针变量只能够存储一个地址编号,假设没有类型。当通过指针就不知道要訪问多少个字节的存储空间
       3、指针区分类型是为了在通过指针訪问它所指向的存储空间的时候,可以正确訪问
       4、假设通过一个char类型的指针操作一个int的变量,假设值的二进制数据超过1字节,那么就造成数据错误
       5、假设通过一个int 类型的指针操作一个char变量,那么你就会改动了你不该改动的内存。造成程序逻辑错误
    #include <stdio.h>
    /*
       全部指针类型都是占用八个字节的存储空间
     
     
     */
    void testEveryPointerIs8B()
    {
        printf("%lu
    ",sizeof(int *));
        printf("%lu
    ",sizeof(char *));
        printf("%lu
    ",sizeof(double *));
        printf("%lu
    ",sizeof(float *));
        printf("%lu
    ",sizeof(float **));
    }
    
    
    
    int main(int argc, const char * argv[]) {
        
        int num = 10;
        
        char *cp = #
    
        
        printf("%d
    ",num);
        
        return 0;
    }
    

    5、指针运算概述
       指针变量:存放是内存字节的地址编号(无符号的整形数)
       指针:是运算受限的无符号的整形数
       运算运算:
       指针 + 整形数 === 指针变量中值 + sizeof(其所指向数据类型)
       指针 - 整数数 === 指针变量中值 - sizeof(其所指向数据类型)
       pointer1 - pointer2 = (pointer1中值 - pointer2中值) / sizeof(其指向数据类型) 
       赋值运算:
        =
        += 必须是一个整形数
        -= 必须是一个整形数
       比較运算
       ==
       != 
       >
       < 
       >=
       <=
       自增自减
       p++; p = p + 1;
       ++p; p = p + 1;
       --p;
       p--;
     
    #include <stdio.h>
    
    
    //算术运算
    void test()
    {
        int a = 10;
        
        int *p = &a;
        //  指针+1
        p = p + 1;
        
        
        int nums[5] = {1,2,3,4,5};
        
        int * pointer1 = nums;
        
        int * pointer2 = &nums[4];
        
        size_t size  = pointer2 - pointer1;    
        printf("%lu
    ",size);        
        //  pointer1 + pointer2;
        //    pointer2 * pointer1;
        //    pointer1 / pointer2;
        //    pointer1 / 2;
    }
    //赋值运算
    void test1()
    {
        int a = 10;
        
        //    int *p = &a;
        
        int nums[] = {1,2,3,4,5};
        
        int *p = nums;
        int *p2 = nums;
        p += 2;
        p = p + 2;
        
        p -= 1;
            
        printf("%d
    ",*p);   
    }
    
    //关系运算
    int main(int argc, const char * argv[]) {
      
        int nums[] = {1,2,3,4,5};
        
        int *p = nums;
        p++;
        int result =  nums == p;
        result = p > nums;
        p--;
        result = p < nums;   
        result = p >= nums;
        result = p <= nums;   
        printf("%d
    ",result);   
        return 0;
    }
    6、指针与一维数组(理解)

     数组像一个指针:訪问数组中元素。使用数组与使用指向这个数组的指针是等价
     
     nums[1] ==== p[1]
     nums+1  ==== p + 1;
     
     nums[1] 的本质 *(nums + 1)
     指针 + 整数 =====  指针中的值 + sizeof(所指向的数据类型) * 整数
    //    int nums[] = {1,2,3,4,5};
    //
    //    int *p = nums;
    double nums[] = {1.0,2.0,3,4,5};
    double * p = nums;
    //    printf("%d,%d,%d,%d,%d,%d ",nums[1],p[1],*(nums + 1),*(p + 1),*(++p),。);
    printf("%p ",nums);
    printf("%p ",nums+2);
    printf("%p ",p);
    printf("%p ",p+2);
      数组不是一个指针
       1、sizeof(array) != sizeof(pointer):当一个数组赋值一个指针变量的时候。那么数组中有些信息就丢失了,比方数组长度。这样的现象指针信息遗失
       2、指针的指向是能够改变的,数组的指向是不能够改变
       3、array == &array 数组名就是数组地址,pointer != &pointer : 指针所指向地址不是指针本身地址

    #include <stdio.h>
    int main(int argc, const char * argv[]) {
        int nums[] = {1,2,3,4,5};
        int *p = nums;
        p = nums;
    //    nums = nums + 1;    
         printf("%lu,%lu
    ",sizeof(nums),sizeof(p));       
        printf("%p
    ",nums);
        printf("%p
    ",&nums);      
        printf("%p
    ",p);
        printf("%p
    ",&p);        
        return 0;
    }

    7、指针与二维数组
    指针数组与二维数组指针变量的差别
    应该注意指针数组和二维数组指针变量的差别。这两者尽管都可用来表示二维数组。可是其表示方法和意义是
    不同的。
    二维数组指针变量是单个的变量。其一般形式中"(*指针变量名)"两边的括号不可少。而指针数组类型表示的
    是多个指针(一组有序指针)在一般形式中"*指针数组名"两边不能有括号。比如:
    int (*p)[3];
    表示一个指向二维数组的指针变量。

    该二维数组的列数为3或分解为一维数组的长度为3。


    int *p[3]
    表示p是一个指针数组。有三个下标变量p[0],p[1],p[2]均为指针变量。

    #include <stdio.h>
    
    void test()
    {
        
        int nums[3][2] = {{1,2},{3,4},{5,6}};   
        int *p = nums[0];    
        printf("%p
    ",p);
        printf("%p
    ",nums);    
        for (int i = 1; i < 6; i++) {
            printf("%d ",*(p + i));
        }
           
    }
    /*
      定义指针数组的格式:
      数据类型 * 指针变量名称[指针个数]
     */
    void test2()
    {
        int nums[3][2] = {{1,2},{3,4},{5,6}};
        
        //    int * p[2] = {nums[0],nums[1]};
        //        p = nums;
        //
        //    printf("%d
    ",p[0][1]);
        
        int a = 10;
        int b = 20;
        int c = 30;
        
        int *p = &a;
        
        //    *p === p[1]; 没有这么写的
        
        int *ps[3] = {&a,&b,&c};
        
        printf("%d,%d,%d",*ps[0],*ps[1],*ps[2]);
        
    }
    /*
      定义一个指向一维数组的指针
      数据类型 (*指针名称)[所指向的一维数组的元素个数]
     
      指针 + 整数 === 指针中的值 + 所指向数据类型的长度 * 整数
     */
    
    int main(int argc, const char * argv[]) {
    
        int nums[3][2] = {{1,2},{3,4},{5,6}};
        
        int (*ps)[2];
        
        ps = nums;//能够觉得ps 与 nums是等价的 
        int num = ps[0][1];
        printf("%d
    ",num);   
        printf("%p
    ",nums);
        printf("%p
    ",nums+1);    
        printf("%p
    ",ps);
        printf("%p
    ",ps+1);    
        for (int i =0 ; i < 3; i++) {
        
            for (int j = 0; j < 2 ; j++) {
                printf("%d ",ps[i][j]);
            }
            printf("
    ");
        }
        
    //    nums   nums[0]
        
    //    同样点:相应地址都是一样的
    //    不同点:指针类型是不同
    //    nums + 1 = nums + sizeof(nums[0])
    //    nums[0] + 1 = nums + sizeof(int)
        
    //   sizeof(nums) 二维数组所用占用存储空间字节数
    //   sizeof(nums) / sizeof(int) 二维数组中一共同拥有多少个int的数据
        
        int *p = nums[0];
        for (int i = 0; i < sizeof(nums) / sizeof(int); i++) {
            printf("%d ",p[i]);
        }
        
      
        return 0;
    }


  • 相关阅读:
    特效优化
    Jsp
    JRebel 热部署
    mysql
    行为树
    Medium | LeetCode 139. 单词拆分 | 动态规划
    Medium | LeetCode 31. 下一个排列
    Easy | LeetCode 27. 移除元素 | 快慢指针
    Medium | LeetCode 437. 路径总和 III | 树 + 回溯 + 前缀和
    Medium | LeetCode 337. 打家劫舍 III | 树后序遍历 + 动态规划
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6905696.html
Copyright © 2011-2022 走看看