• C 入门 第八节 指针


    void changeValue(int num1,int num2)
    {
        int temp = num1;
        num1 = num2;
        num2 = temp;
    }
    //指针作为函数的参数进行传递,可以实现形参的改变作用到实参

    void changeValue2(int *p1,int *p2)
    {
        int temp = *p1;
        *p1 = *p2;
        *p2 = temp;
    }

    //字符指针作为形参
    void func2(int *a,int count)
    {
        for (int i = 0; i < count; i ++)
        {
            printf("%d ",*(a+i));
        }
        printf(" ");
    }

    int main(int argc, const char * argv[]) {
       
    /*
        1. 程序运行时,系统会为税局分配内存单元,存储数据.
        2. 内存是由多个连续的内存单元组成
           内存单元用于存储数据,每个内存单元占一个字节,一个字节==八个二进制位
           内存单元地址:内存单元的编号,连续的.便于访问内存单元,就像门牌号一样.(图2)
        3. 数据如何存储(图3)
        4. 访问数据的两种方式;
           (1) 直接访问.定义变量存储数据,通过变量名访问数据/
        int a = 10;
        int b = a; //通过变量a访问内存中的数据
        
           (2) 间接访问/通过内存单元地址,访问内存中的数据,任何数值都是存储在内存中的存储单元中.
        5. 内存单元的地址被称为指针
            指针变量: 存储指针(地址)的变量
            定义一个指针变量
        int*p = NULL;
        float *q = NULL;
        char *r = NULL;
        NULL 是空指针;相当于0.NULL是给指针变量赋值的
        定义指针变量的语法
        类型修饰符 *指针变量名 = 初始值(地址)
        * 表示:定义的变量是一个指针变量,存储的内容是地址.
        类型修饰符表示:地址指向的存储单元中数据的类型(即通过地址找到的数据的类型)
        指针变量的类型:类型修饰符 *    指向某种类型数据的指针类型
        p的类型 int *    指向整型数据的指针类型
        q的类型 float *  指向浮点型数据的指针类型
        r的类型 char *   指向字符型数据的指针类型
        指针变量通常被称为指针
        p 整型指针
        q 浮点型指针
        r 字符型指针
        
        通过指针访问存储单元,必须先获取存储单元的地址
        取地址运算符 & 获取变量的地址
        输出地址 %p
        int a = 100;
        printf("变量a的存储单元地址:%p ",&a);
        float b = 1.5;
        printf("变量b的存储单元地址:%p ",&b);
        char c = 'a';
        printf("变量c的存储单元地址:%p ",&c);
        printf("----------------------------- ");
    //    定义指针存储地址
    //    要求:指针的类型修饰符 和 指针指向的变量的类型必须一致
        int *p = &a;
    //   (int *)p = &a; 指针p指向变量a的存储单元(指针p中存储的地址是变量a的存储单元地址)
        
        printf("指针p中存储的地址:%p ",p);
        float *q = &b;// * 在定义指针的时候,只起到修饰作用,说明,我定义的是一个指针变量
        printf("指针q中存储的地址:%p ",q);
        char *o = &c;
        printf("指针o中存储的地址:%p ",o);
        printf("----------------------------- ");
        
    //    通过指针访问存储单元
    //    访问变量的存储单元的值
        printf("%d ",*p); // *p 获取p指向的 内存地址中的值
        
        int i = *p;    // i = a;
        float j = *q;  //j = b;
        char k = *o;   //k = c;
        
        printf("i = %d j = %.2f k = %c " ,i ,j ,k);
        
    //使用修改数
        a = 200;
        b = 2.5;
        c = 'b';
        printf("a = %d *p = %d ",a ,*p);

    // 使用指针修改
        *p = 300;
        *q = 3.5;
        *o = 'c';
        
        printf("b = %.2f *q = %.2f ",b ,*q);
     
    //    & 和 * 是配套使用的,互为逆运算
    //  & 获取变量存储单元地址
    //  * 通过地址访问变量的存储单元

    // 练习
        int x = 0;
        int y = 0;
        int *m = NULL; //指针m 指向空指针位置
        m = &x; //指针m 重新 指向变量x
        *m = 10; // *m 通过 m  存储的地址访问变量x的存储单元,读取x的值
        printf("%d ",*m);
        
        m = &y;
        *m = 20;
        printf("%d ",*m);
        
    //指针的存储空间与操作系统有关
    //32位操作系统中占4个字节,64位操作系统中占8个字节
        printf("%lu ",sizeof(m));

    // 区分指针中的 * 的作用
        1. 如果是在定义指针变量的时候, int *p = NULL; 这个 * 代表的是p是一个指针变量.
        2. 如果定义完成再使用*p的时候,*表示的是取出p指向的地址里面的数据.是取值运算符
     
        指针的运算
        指针只有加减运算
        定义指针时的类型决定指针移到几个字符

        第一种: p + n
        表示: 从p指向的存储单元向高位偏移n个数据类型的字节数(n * 数据类型的字节数)
        p的指向没有改变

        
        int a = 100;
        int *p = &a;
        printf("%p ",p);
        printf("%p ",p + 1);
        printf("%p ",p + 2);
        
        //第二种: p - n
        表示: 从p指向的存储单元向低位偏移n个数据类型的字节数(n * 数据类型的字节数)
        
        第三种: p ++ 或者 ++ p
        指针向高地址移动,移动的距离是指针指向数据类型所占的字节数
        p的指向改变了

        int a = 200;
        int *p = &a;
        printf("%p ",p);
        //printf("%p ",p ++);
        printf("%p ",++ p);
    */
    /*
         //    1. 定义一个数组
         int a[5] = {1,2,3,4,5};
         //    2. 访问数组元素 数组名[下标]
         a[0] = 10;
         printf("%d ",a[0]);
         //    3. 计算数组元素个数
         printf("%lu ",sizeof(a));
         printf("%lu ",sizeof(int));
         printf("%lu ",sizeof(a[0]));
         printf("%lu ",sizeof(a)/sizeof(int));
         printf("%lu ",sizeof(a)/sizeof(a[0]));
         //    4. 数组名是常量,表示数组首元素的地址 a = &a[0]
         
         #pragma mark --------指针与数组------------
         
         指针可以指向变量,读取变量存储单元中的值
         指针可以指向数组元素,数组在内存中是一段连续的存储空间,每个元素都占有相应的存储单元.
         数组元素的指针即数组元素的地址
         
         访问数组元素可以使用数组名或者指向数组的指针
         访问数组元素的两种方式: 下标法 , 指针法
         
         1. 下标法
         
         int a[5] = {1,2,3,4,5};
         int *p = a; //数组名是常量,表示数组首元素的地址 &a[], 此时,p指向数组的第一个元素的存储单元,表示首元素地址.
         
         //   使用数组名
         
         printf("%d %d ",a[0],a[1]);
         
         printf("%d %d ",p[0],p[1]);
         
         
         
         // 使用指针
         for (int i = 0; i < 4; i ++)
         {
         for (int j = 0; j < 4 - i; j ++)
         {
         if (p[j] < p[j + 1])
         {
         int c = 0;
         c = a[j];
         p[j] = p[j + 1];
         p[j + 1] = c;
         }
         }
         }
         for (int i = 0; i <5; i ++)
         {
         printf("%d ",p[i]);
         
         }
         
         2. 修改指针指向,不能使用数组名,只能使用指针;
         
         printf("%d ",*p); //指向a[0]
         
         // 修改 等价
         int b[5] = {1,2,3,4,5};
         int *q = b;
         b[1] = 20;
         q[1] = 30;
         *(q + 1) = 10;
         *(b + 1) = 20;
         for (int i = 0; i <5; i ++)
         {
         printf("%d ",b[i]);
         }
         
         指针和数组的区别
         指针和数组都可以通过下标法和指针法访问数组元素
         
         1. 指针可以修改指向
         数组名 是常量,表示首元素的地址,不能改变
         
         2. 指针的存储空间;4/8字节
         数组的存储空间: 元素个数*元素的存储空间
         
         3. sizeof (数组名) 得到的是数组的存储空间
         sizeof (指针)得到的是4/8字节,不管指针指向的存储空间存储的是哪种数据.
         char a[3] = {'a','b','c'};
         char *f = a;
         printf("%lu ",sizeof(f));
         
         指针类型和数组元素类型不匹配会怎样
         
         short a[4] = {6,7,8};
         int *p = a;
         printf("%d ",*p);
    */
    #pragma mark ----------指针与字符串-----------
    /*
        //    定义字符数组存储字符串,str在栈区中存放,常量字符串拷贝的副本存储在字符数组中,数组中的元素是可以改变的
        char str[] = "hello";
        char *p = str;
        //  使用指针取修改数组元素
        *p = 'a';
        //使用指针放问数组元素
        for (int i = 0; i < 6; i ++)
        {
            printf("%c ",*(p+i));
        }
        printf(" ");
        //使用指针操作字符串
        printf("%s ",p);
     
        
        定义字符指针指向字符串
        ""常量字符串 , 存储在常量区,只能访问不能修改
        定义指针指向常量区的字符串常量的首地址,指针p中只是存储地址

        char *p = "hello";
     //   *p = 'a';
        可以访问字符和字符串
        printf("%s ",p);
        printf("%c ",*p);

    //总结: 指向数组的指针可以访问和修改数组元素;指向常量字符串的指针只能访问不能修改.
        
    //练习 : 通过指针计算字符串长度
        char str[] = "iphone";
        char *p = str;
        int n = 0;
        while (p[n] != '') // *(p+n)!=''
        {
            n ++;
        }
        printf("%d ",n);
    */
        
    #pragma mark -------------指针数组---------------
    /*
    //  二维数组存储 字符串 数组的数组
        char strs[3][5] = {"ios","ipad","imac"};
    //  strs存储的数组元素是字符数组(字符数组中存储的是字符串,常量字符串的副本)
        printf("%s ",strs[0]); //strs[0]第一个字符数组的首元素地址.可以访问字符数组
        strcpy(strs[0], "mac");
        printf("%s ",strs[0]);
    // 指针数组 数组中的元素都是指针
        char *strs[3] = {"iOS","iPad","iMac"};

        strs本质是一维数组
        strs存储的数组元素是字符指针(字符指针指向常量字符串)
        strs[0]第一个字符指针,指向常量区的"iOS"
        strs[1]第二个字符指针,指向常量区的"iPad"
        strs[2]第三个字符指针,指向常量区的"iMac"

        char *strs[3] = {"iOS","iPad","iMac"};
        printf("%s ",*strs);
        printf("%s ",*(strs+1));
    //   修改
        strs[0] = "Symban"; //strs[0] 访问的是字符指针,指针的重新指向另一个常量字符串
        printf("%s ",strs[0]);

     */
      //  指针与函数 指针作为函数的参数
        
        int num1 = 30;
        int num2 = 90;
        changeValue(num1, num2);
        printf("%d %d ",num1,num2);
        changeValue2(&num1, &num2);
        printf("%d %d ",num1,num2);

    // 字符指针作为实参
    //    int *p = a;
    //    func1(p,5);
    //    func2(p, 5);

  • 相关阅读:
    正则化--Lambda
    uwsgi配置cheaper模式进行自动弹性
    采集容器内存并写到excel
    通过进程id找到进程对应的容器并统计每个进程的内存占用写到excel里
    基于celery的任务管理
    基于Redis做内存管理
    uWSGI
    nginx
    服务发现
    绑核与巨页
  • 原文地址:https://www.cnblogs.com/wangshuai-1129/p/5079084.html
Copyright © 2020-2023  润新知