最近在基于redis的c客户端hiredis做扩展的时候, 其中一个函数需要接受一个const char **的二级指针作为参数:

  

void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);

这个函数主要是用于 需要传递多个string值的场景,类似于 lpush, del key1 key2…, zadd key score1 member1 score2 member2…这类命令, 其中 argc是传递参数的个数, argv主要用于传递的string的value, 而argvlen 是每个string的size, 这里不讲解这个函数的具体用法,主要谈下如何构造这样一样二级指针,也算对c/c++基础内容的一个回顾。

  我们都知道, 指针是c/c++中一种非常有用的数据类型, 用于存储一个数据的地址。一个指针有三种状态:   保存一个特定对象的地址; 指向某一个特定对象后边的某一个对象; 0值。 另外, 我们在定义一个指针的时候, 一定要记得初始化: int *p = 0。   指针有一级指针和多级指针之分, 一级指针比较简单,也比较好理解。而多级指针,就需要花点心思了,特别是c/c++这类需要手动管理内存的语言,使用的时候,更是要谨慎。 

  当我们在使用这个函数执行redis命令的时候, 所传递的string的个数通常是不确定的;所以这里就没法使用数组了(我们知道, 一维数组可以作为一级指针使用, 二维数组可以使用二级指针使用), 得使用动态内存分配了,代码实例:

  

 int getCommandArgv(const vector<string> &vecArgs,   char **&argv) {
        int argsLen = vecArgs.size();
        char **arrArgv = new char*[argsLen];
        vector<string>::const_iterator it = vecArgs.begin();
        for (; it != vecArgs.end(); it++) {
            string tmpArgs = (*it);
            arrArgv[i] = new char[tmpArgs.size()];
            memcpy(arrArgv[i], tmpArgs.c_str(), tmpArgs.size());
            i++;
        }

for (int i = 0; i < argc; i++) {
                if (argv[i] != NULL) {
                    delete [] argv[i];
                    argv[i] = NULL;
                }
            }
        delete [] argv;
        argv = NULL;
return 0; }

如代码所示,展示了如何把一个保存string的vector如何存储到一个char ** 的二级指针中。在给二级指针分配内容的时候, 不仅要给这个二级指针分配内存,同时,也要给它里边的每一个元素分配内存;   但最后一定不要忘了释放内存哦, 释放的时候, 需要先释放其中每一个元素指向的内存空间, 最后在释放这个二级指针指向的内存空间。

  最后, 讲一下指针和const限定符。 根据《c++  primer》 里边描述的, 有 1: 指向const对象的指针, 2: const指针, 前者是指针指代的内容为const, 内容不可改变, 但指针本身的值可以改变; 后者为const指针, 指代的内容可以改变, 指针本身的值不可改变。