• 指针的应用


    一.数组与指针

     1.指针数组(存放指针的数组

      例如:char *p[10]; float *p[10];int * q[4][3];

      ♦ 一个数组,及其元素均为指针类型的数据——指针数组

       一维指针数组:类型名 数组名[数组长度];

       二维指针数组:类型名 数组名[行][列];

       • 一维数值指针数组:

         int array[8]  = {1,2,3,4,5,6,7,8};

         int *p[6] = {&array[0],&array[1],&array[2],&array[3]};

         p[4] = &array[4];

         p[5] = &array[5];

       • 二维数值指针数组:

         int *a[2][3];

         a[0][1] = &array[0];

       • 指针数组与字符串的联系:

         char *name[2] = {"hello","world"};

         name[0] = "hello";

         name[1] = "world";

        数组中存放的是字符串的首地址,而不是字符串。

    //指针数组
    #include <stdio.h>
    
    int main(int argc,char *argv[])
    {
        char *name[] = {"Follow me","BASIC","Grate Wall"};
        int i;
        for(i = 0;i < 3;i++)
        {
            printf("%s",name[i]);
        }
        return 0;
    }

     2.数组元素指针(指向数组元素的指针)

      ♦ 数组元素在内存中分配的地址——数组元素的指针

       • 定义一个指向数组元素的指针

         int a_1[10];

         int a_2[5][5];

         int *p,*q;

         p = &a_1[0];  //一维数组元素的指针

         q = &a_2[1][1];  //二维数组元素的指针

       • 在C语言中,设定一维数组名代表了数组第一个元素的地址。

         int array[5];

         int *p;

         p = array[0];  等价于  p = array;

       • 引用数组元素

        1.下标法:array[1];

        2.指针法:*(p + i);或*(array+i);

         • array为数组的首地址是一个常量,不能进行array++或++array操作。

         • p是变量,其值为array数组的首地址,可以进行++操作。

    //采用指针法引用数组元素
    #include <stdio.h>
    int main(int argc,char *argv[])
    {
        int a[5],i,*pa,*pb;
        pa = a;    //数组名代表数组首地址
        pb = &a[0];    //数组的第一个元素的地址也代表数组首地址
        for(i = 0;i < 5;i++)
        {
            a[i] = i;
            printf("a[%d] = %d
    ",i,a[i]);    //0 1 2 3 4
            printf("a[%d] = %d
    ",i,*(a+i));    //0 1 2 3 4
            printf("a[%d] = %d
    ",i,*(pa+i));    //0 1 2 3 4
            printf("a[%d] = %d
    ",i,*pb++);    //0 1 2 3 4
        }
        //printf("a[%d] = %d
    ",i,a++);    //a为常量,不能进行++操作
        return 0; 
    }

      3.数组指针(行指针)(指向数组的指针)

      ♦ 数组元素在内存中的起始地址——数组元素的指针

       • 定义一个数组元素的指针

         int a[10]  = {1,2,3,4};

         int *p = a;  //p为数组元素的指针

       • 数组在内存中的起始地址称为数组的指针

         int a[10] = {1,2,3,4};

         int (*q)[10]  = &a;  //q为指向数组的指针

         a为一维数组名,代表数组第一个元素的指针。

         &a:对a取地址,代表将整个数组当做一个整体,将这个地址付给q——数组指针。

    //数组指针
    #include <stdio.h>
    
    int main(int argc,char *argv[])
    {
        int a[5] = {1,2,3,4,5};
        int (*p)[5]  = &a;    //定义一个一维数组,指向一个一维数组
        printf("%d
    ",*((int *)(p+1)-1));    //5,p+1移动整个数组的长度
        return 0;
    }

       • 指向二维数组的数组指针

         int a[3][4] = {{1,3,2,4},{5,6,7,34},{5,9,6,8}};

         int (*p)[4] = a;

         p等价于指向二维数组第0行,可完全替代a的作用。

       • 二维数组名

         • 二维数组名是一个二级指针

         • a代表了二维数组第0行的行地址

         • a+1代表了第一行的行地址

         • *(a+1)代表了第1行第0列元素的地址

         • *(a+1)+2代表了第1行第2列元素的地址

         • *(*(a+1)+2)代表了第1行第2列元素

       • 多维数组与指针

    表示形式 含义
    a 数组名,指向一维数组a[0],即0行首地址
    a+1、&a[1] 1行首地址
    *(a+0)、*a、a[0] 0行0列元素地址
    *(a+1)、(*(a+1)+0)、a[1] 1行0列元素a[1][0]的地址
    *(a+1)+2、a[1]+2、&a[1][2] 1行2列元素a[1][2]的地址
    *(a[1]+2)、*(*(a+1)+2)、a[1][2] 1行2列元素a[1][2]的值
    //数组指针
    #include <stdio.h>
    int main(int argc,char *argv[])
    {
        int a[3][5]={
                      {1,2,3,4,5},
                      {6,7,8,9},
                      {14,12,23,66}
                    };
        int i,j;
        int (*p)[5] = a;    //定义一个数组指针指向一个二维数组
        for(i = 0;i < 5;i++)    //采用数组指针打印二维数组的第一行
            printf("%d
    ",*(p[0]+i));
        for(i = 0;i < 5;i++)    //采用数组指针打印二维数组的第二行
            printf("%d
    ",*(p[1]+i));
        for(i = 0;i < 3;i++)    //采用数组指针打印二维数组的全部内容
        {
            for(j=0;j<5;j++)
            {    
                printf("%d	",*(p[i]+j));
                if(j == 4)
                    printf("
    ");
            }
        }
        return 0;
    }

    二.函数与指针

     1.指针作函数参数

      • 指针变量作函数的参数

    //指针作函数的参数
    #include <stdio.h>
    
    int exchange1(int p1,int p2)
    {
        int temp;
        temp = p1;
        p2 = p1;
        p2 = temp;  
    }
    
    int exchange2(int *p1,int *p2)
    {
        int temp;
        temp = *p1;
        *p1 = *p2;
        *p2 = temp;
    }
    
    int main(int argc,char *argv[])
    {
        int a,b;
        scanf("%d %d",&a,&b);    //a = 9,b = 3
        if(a > b)
            //exchange1(a,b);    //a = 9,b = 3
            exchange2(&a,&b);    //a = 3,b = 9
        printf("a = %d,b = %d
    ",a,b);
        return 0;
    }

      • 一维数组名作函数的参数

    //一维数组名作函数的参数
    #include <stdio.h>
    
    // int max(int a[],int num)    //数组作形参时,无需指定下表
    int max(int *a,int num)    //数组名作形参时,将演变为指针
    {
        int i,max;
        max = a[0];
        for(i = 0;i  < num;i++)
        {
            if(a[i] > max)
                max = a[i];
        }
        printf("a_len = %d
    ",sizeof(a));    //a_len = 4
        return max;
    }
    
    int main(int argc,char *argv[])
    {
        int a[5] = {4,7,9,6,5};
        printf("max = %d
    ",max(a,5));    //max = 9
        return 0;
    }

         • 数组名作形参时,无需指定其下标。

         • 数组名作形参时,将演变为指针。

      • 二维数组名作函数的参数

    //一维数组名作函数的参数
    #include <stdio.h>
    
    // int max(int a[][3],int x,int y)    //二维数组名作形参时,行可以不写出来,列必须写出来
    int max(int (*a)[3],int x,int y)    //数组指针作形参,完全等价于二维数组的应用
    {
        int i,j,max;
        max = a[0][0];
        for(i = 0;i  < x;i++)
        {
            for(j = 0;j < y;j++)
            {
                if(a[i][j] > max)
                    max = a[i][j];
            }
        }
        printf("a_len = %d
    ",sizeof(a));    //a_len = 4
        return max;
    }
    
    int main(int argc,char *argv[])
    {
        int a[2][3] = {
                        {4,7,9},
                        {11,6,5}
                      };
        printf("max = %d
    ",max(a,2,3));    //max = 11
        return 0;
    }

         • 二维数组名作参数,行可以不写出来,列必须写出来。

         • 数组指针作形参,完全等价于二维数组的应用。

     2.指针作函数返回值

       • 返回指针值的函数,一般定义形式:类型名 *函数名(参数列表);例如:int *fun(int x,int y);

       • 在调用时要先定义一个适当的指针来接收函数的返回值,这个适当的指针其类型应为函数返回指针所指向的类型。

         char *pc = NULL;

         pc = (char *)malloc(100 * sizeof(char));  //表示分配100个字节的内存空间,并强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc

     3.指向函数的指针(函数指针)

      ♦ 一个函数在编译时被分配一个入口地址,这个地址就称为——函数的指针。

        • 函数名代表函数的入口地址。

        • 指向函数指针变量的定义格式:int (*p)(int,int);

          例如:int (*p)(int,int);

             p = max;  //将函数的入口地址赋给函数指针变量p

             c = (*p)(a,b);  //调用max函数

          • 说明:

            • p不是固定指向哪个函数的,而是专门用来存放函数入口地址的变量,在程序中把哪个函数的入口地址赋给他,它就指向哪个函数。

            • p不能像指向变量的指针变量一样进行p++、p--等无意义的操作。

      ♦ 函数指针的应用——回调函数(钩子函数)

        • 函数指针变量常见的用途之一是把指针作为参数传递到其它函数。

        • 指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。

    //函数指针
    //process称为回调函数,process并没有直接调用max、min、add函数,而是通过fun函数指针接收相应函数首地址,进行调用,调用后把结果返回给主调函数main
    #include <stdio.h>
    
    int max(int x,int y)
    {
        return x>y?x:y;
    }
    
    int min(int x,int y)
    {
        return x<y?x:y;
    }
    
    int add(int x,int y)
    {
        return x+y;
    }
    
    int process(int x,int y,int (*fun)(int ,int ))    //回调函数
    {
        int result;
        result = (*fun)(x,y);
        return result;
    }
    
    int main(int argc,char *argv[])
    {
        int a,b,result;
        
        printf("input a and b:");
        scanf("%d %d",&a,&b);
        
        result = process(a,b,max);
        printf("max = %d
    ",result);
        
        result = process(a,b,min);
        printf("min = %d
    ",result);
        
        result = process(a,b,add);
        printf("add = %d
    ",result);
        return 0;
    }

    三.其它特殊指针

     1.main函数带参  ./a.out hello peter ……

       • main函数可以接收来自操作系统或者其它应用传递的参数。

       • int main(int argc,char *argv[])

       • 说明:

         • argc代表参数的个数

         • argv存放各参数首地址(系统把每个参数当作一个字符串放在系统缓冲区,把首地址放在指针数组中)

         • ./a.out hello peter …… 依次存放在argv[0] argv[1] argv[2] …… 中

    //main函数传参
    //如执行    ./a.out hello lucy
    //输出:
    // argc = 3
    // argv[0] = ./a.out
    // argv[1] = hello
    // argv[5] = lucy
    
    #include <stdio.h>
    
    int main(int argc,char *argv[])
    {
        int i;
        printf("argc = %d
    ",argc);
        for(i = 0;i < argc;i++)
            printf("argv[%d] = %s
    ",i,argv[i]);
        return 0;
    }

     2.指向指针的指针  char **p

      ♦ 一个变量有自己的地址,我们可以用一个指针变量指向它,指针变量同样也是变量,我们也可以定义另一个指针指向这个指针变量——指向指针的指针

        int a;

        int *p = &a;

        int *q = &p;

      ♦ 通过函数改变指针的指向

    //通过函数改变指针的指向
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    void GetMemory1(char *p,int num)    //泄露一块内存
    {
        p = (char *)malloc(num * sizeof(char));
    }
    
    void GetMemory2(char **p,int num)    //在子函数内部改变主调函数定义指针的指向
    {
        *p = (char *)malloc(num * sizeof(char));
    }
    
    int main(int argc,char *argv[])
    {
        char *str = NULL;
        // GetMemory1(str,100);    //段错误
        GetMemory2(&str,100);    //hello kitty
        strcpy(str,"hello kitty");
        printf("str = %s
    ",str);
        free(str);
        return 0;
    }

     3.void类型的指针  void *指针

      ♦ void指针是一种很特别的指针,并不指定它是指向哪一种类型的数据,而是根据需要转换为所需数据类型。

        int a = 0;

        float b = 0;

        void *p = &a;

        void *q = &b;

      ♦ 常用于函数的返回值和参数,用于不确定类型指针指向

        void malloc(unsigned int num_types);

        void memset(void *str,char ch,size_t n);

     4.函数指针数组

      函数指针数组的定义  例如:int * (*p[10])(int a[3][4],int num)  //定义了一个函数指针数组,带有两个参数,返回值为int *类型

  • 相关阅读:
    Linux环境下MySQL报Table 'xxx' doesn't exist错误解决方法
    mysql主主复制(双主复制)配置步骤
    MHA安装手记
    MySQL MHA配置
    innobackupex 还原和备份实例
    scp命令
    给想进入餐饮业新手一些建议
    mysql mha 主从自动切换 高可用
    mysql innobackupex xtrabackup 大数据量 备份 还原
    MySQL主从复制、半同步复制和主主复制概述
  • 原文地址:https://www.cnblogs.com/lemongirl/p/7895402.html
Copyright © 2020-2023  润新知