• 指针的指针(二)


    实例

    这里接上一章指针的指针(一)

    这里有几个例子程序,用于说明指针表达式的一些常用用法。我们先看下面这张图片,text是一个char类型的二维数组,而cp是指向这个二维数组的一个指针数组,strings是指向cp地址的指针

     

     接下来,我们看一下下面这段代码,我们要在text这个二维数组中查找一个字符,查找方法实现在find_char这个函数中

    #include <stdio.h>
    #include <assert.h>
    #define TRUE 1
    #define FALSE 0
    
    int find_char(char **strings, int value)
    {
        assert(strings != NULL); //<8>
        while (*strings != NULL) //<9>
        {
            while (**strings != '') //<10>
            {
                if (*(*strings)++ == value) //<11>
                {
                    return TRUE;
                }
            }
            strings++; //<12>
        }
        return FALSE;
    }
    
    int main(int argc, char const *argv[])
    {
        char text[6][10] = {"spring", "struts", "hibernate", "flask", "numpy", "sklearn"}; //<1>
        char *cp[6];                                                                       //<2>
        int i = 0;
        for (; i < 6; i++)
        {
            cp[i] = text[i]; //<3>
        }
        char **strings = &cp[0]; //<4>
        char *before = cp[0];    //<5>
        printf("before find_char:
    ");
        for (i = 0; i < 6; i++)
        {
            printf("cp[%d] = %p
    ", i, cp[i]); //<6>
        }
        int res = find_char(strings, 'g'); //<7>
        printf("res = %d
    ", res);
        printf("after find_char:
    ");
        for (i = 0; i < 6; i++)
        {
            printf("cp[%d] = %p
    ", i, cp[i]); //<13>
        }
        char *after = cp[0];                                                             //<14>
        printf("before = %p
    after = %p
    diff = %d
    ", before, after, (after - before)); //<15>
        return 0;
    }
    

            

    现在我们来分析一下上面的程序,下面的标号与程序注释中的标号一一对应

    1. 我们先声明一个名称为text的二维数组,这个数组里有6个字符串,每一个字符串都是字符数组
    2. 声明一个名为cp的指针数组
    3. 将指针数组中的每个元素,指向text每个字符串的起始地址
    4. 声明一个指向指针的指针strings,用指针数组cp的起始位置(即&cp[0])来初始化
    5. 这里声明一个指针before,保存cp[0]最开始指向的位置
    6. 打印指针数组每个元素指向的位置
    7. 传入指向指针的指针stings,和我们要查找的字符'g'
    8. 这里,我们进入到find_char()函数中,检查传入指向指针的指针是否为NULL,
    9. 如果strings保存的值不为空,则进入循环
    10. 简单分析一下**strings,从右到左,strings保存的是一个指针数组的初始位置,所以*strings首先间接访问到cp指针数组的第一个值,这里是一个地址,**strings则是再次对cp数组第一个元素所保存的地址进行间接访问,访问到text第一个字符串的第一个元素,为一个字符,这里判断当前字符是否为'',如果是则代表到了字符串的末尾了。如果**strings当前的指向的字符不为'',则进入循环
    11. *(*strings)++是一个很有趣的表达式,我们来分析一下,首先是*strings参与运算,strings指向的是cp第一个元素的地址,所以*strings则是指向cp第一个元素的值,然后再进行++运算,这里先返回一个*string的值的拷贝,再对*strings指向的那个值+1,即在cp第一个元素所保存的值+1,这时候cp已经指向text下一个字符串的起始地址,而前一个*拿着之前(*string)++的运算结果,这里还是指向text的第一个地址,然后用*进行间接访问,获取该地址的值,比较是不是要查找的value元素。(*string)++会一直循环,即cp第一个元素指向的地址不断往后,一直到*(*strings)++指向一个'',代表当前的字符串(即数组)结束
    12. string++则是将string当前保存的地址指向后一个地址
    13. 执行完find_char()函数后,我们打印cp指针数组中每一个元素的值,如果不出意料,cp元素第一个值已经和执行find_char()之前不一样了
    14. 初始化一个指针after,将cp指针第一个元素的值赋给它,用于和之前的before比较
    15. 打印before、after的值,并计算指针之间的距离

    下面,我们运行一下代码看一下效果:

    # gcc main.c -o main
    # ./main 
    before find_char:
    cp[0] = 0x7fffadcd5250
    cp[1] = 0x7fffadcd525a
    cp[2] = 0x7fffadcd5264
    cp[3] = 0x7fffadcd526e
    cp[4] = 0x7fffadcd5278
    cp[5] = 0x7fffadcd5282
    res = 1
    after find_char:
    cp[0] = 0x7fffadcd5256
    cp[1] = 0x7fffadcd525a
    cp[2] = 0x7fffadcd5264
    cp[3] = 0x7fffadcd526e
    cp[4] = 0x7fffadcd5278
    cp[5] = 0x7fffadcd5282
    before = 0x7fffadcd5250
    after = 0x7fffadcd5256
    diff = 6
    

      

    确实如我们之前所分析,cp[0]这个元素所保存的值在find_char()执行之前和执行之后有所变化。

    上面的程序确实可以在一个二维数组中查找一个字符,但它并不完美,因为主方法main()中的cp变量的值改变了,如果cp这个值在后续还要用到的话,那我们又要重新声明一个指针数组或者复用cp指针数组,将text中每个字符串的地址挨个挨个赋值过去,有没有办法在查找的时候不改变cp变量的值呢?肯定是有的,下面让我们看另外一个find_char()方法,这里省略了main主函数

    int find_char(char **strings, char value)
    {
        char *string;                         //<1>
        while ((string = *strings++) != NULL) //<2>
        {
            while (*string != '') //<3>
            {
                if (*string++ == value) //<4>
                {
                    return TRUE;
                }
            }
        }
    
        return FALSE;
    }
    

      

    1. 先声明一个指针string
    2. *strings++这个表达式,首先string++先返回一个strings保存的值的一份拷贝,然后对strings所保存的值+1,指向下一个内存地址,然后再用*进行之前strings所指向的地址间接访问,这里仍然访问的是ch的第一个元素,尽管这时候strings已经指向ch的的第二个元素了
    3. 通过上一个步骤,string的值为ch指针数组中的一个元素,即为地址,再用*进行间接访问,访问到text中的元素的第一个字符,判断不为''则代表字符串还未结束
    4. *string++首先是返回string所保存的值的一份拷贝,再对string+1,将string的值指向原先的下一个地址,然后*拿着原先的拷贝进行间接访问,一直循环到找到想要的字符为止

    这里,我们将现在的find_char()函数替换上一个find_char()函数,再看看运行结果

    # gcc main.c -o main
    # ./main 
    before find_char:
    cp[0] = 0x7ffd0e28f970
    cp[1] = 0x7ffd0e28f97a
    cp[2] = 0x7ffd0e28f984
    cp[3] = 0x7ffd0e28f98e
    cp[4] = 0x7ffd0e28f998
    cp[5] = 0x7ffd0e28f9a2
    res = 1
    after find_char:
    cp[0] = 0x7ffd0e28f970
    cp[1] = 0x7ffd0e28f97a
    cp[2] = 0x7ffd0e28f984
    cp[3] = 0x7ffd0e28f98e
    cp[4] = 0x7ffd0e28f998
    cp[5] = 0x7ffd0e28f9a2
    before = 0x7ffd0e28f970
    after = 0x7ffd0e28f970
    diff = 0
    

      

    这里我们可以看到,执行find_char()函数后,没有再改变ch变量的值

  • 相关阅读:
    access remote libvirtd
    python中获取当前所有的logger
    python标准库xml.etree.ElementTree的bug
    python Requests库在处理response时的一些陷阱
    Ubuntu12.04下安装Subversion并进行配置
    命令行打包war包
    Ubuntu12.04安装MariaDB并修改字符集为UTF-8
    Windows下Navicat远程连接Linux下MySQL服务器错误1130
    解决ubuntu下eth0不显示
    解决Ubuntu12.04下rpcbind: cannot open '/var/run/rpcbind/rpcbind.xdr' file for reading
  • 原文地址:https://www.cnblogs.com/beiluowuzheng/p/9307383.html
Copyright © 2020-2023  润新知