zoukankan      html  css  js  c++  java
  • 指针的应用

    一.数组与指针

     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 *类型

  • 相关阅读:
    cf B. Sereja and Suffixes
    cf E. Dima and Magic Guitar
    cf D. Dima and Trap Graph
    cf C. Dima and Salad
    最短路径问题(floyd)
    Drainage Ditches(网络流(EK算法))
    图结构练习—BFSDFS—判断可达性(BFS)
    Sorting It All Out(拓扑排序)
    Power Network(最大流(EK算法))
    Labeling Balls(拓扑)
  • 原文地址:https://www.cnblogs.com/lemongirl/p/7895402.html
Copyright © 2011-2022 走看看