C语言中的多级指针

前言

C语言中指针,可以算是最灵活,最强大的地方,同时也是最艰深的地方。用不好的话,什么段错误,内存违例等以前没见过的东西都会跳出来。最近看《UNIX系统编程》 ,感觉能把C语言用到这个水平,才能算是登堂入室。

一般来说,我们会把指针跟数组联系起来理解,比如*p就是一个一维数组,**p是两维数组等,而一般而言,见到两维的指针也算是难得了,更高维的只怕看一会就会晕掉。《UNIX系统编程》 中有个关于参数列表的例子,感觉对指针运用的已经到出神入化的境地,所以贴出来大家参考一下。

 

指向指针的指针

在C语言的入口main函数中,有一个**argv参数,指明命令行参数,一般写法是这样:

C代码
  1. int  main( int  argc,  char  **argv){  
  2.     /*  
  3.      * code here.  
  4.      */   
  5. }  

 

这个**argv,是一个指向指针的指针,用来将命令行参数保存下来,比如,输入一条命令:

prog -c -v 200

 **argv中的内容即为 prog, -c, -v, 200. 因为prog, -c等的长度不等,就需要一个指针来引用他们,而prog后边接几个参数也是不定的,所以有需要有一个指针来引用,所以就是这里的二维指针了。画一个table可能看起来比较清晰一些:

 

 

prog
-c
-v
200

 

再考虑这样一种情况,shell程序,对于你会输多少行命令也是不知道的,那它就需要再多一个指针来引用你会有多少个命令输入。这就是我们今天要看的(***ptr)了。

 

指向"指针的指针"的指针

书中的例子是这样,先看下函数的原型: 

C代码
  1. int  makeargv( const   char  *s,  const   char  *delimiters,  char  ***argvp);  

 

函数接受三个参数,第一个是要分析的串,第二个是界定符序列,第三个是生成的"指针的指针"(即二维数组)的指针。实现比较简单,主要是看其中关于指针的用法:

C代码
  1. /*  
  2.  * author : juntao.qiu  
  3.  */   
  4. int  makeargv( const   char  *s,  const   char  *delimiters,  char  ***argvp){  
  5.     int  error;  
  6.     int  i;  
  7.     int  numtokens;  
  8.     const   char  *snew;  
  9.     char  *t;  
  10.   
  11.     if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)){  
  12.         error = EINVAL;  
  13.         return  -1;  
  14.     }  
  15.   
  16.     *argvp = NULL;  
  17.     snew = s + strspn(s, delimiters);  
  18.     if ((t = malloc(strlen(snew)+1)) == NULL)  
  19.         return  -1;  
  20.   
  21.     strcpy(t, snew);  
  22.     numtokens = 0;  
  23.   
  24.     if (strtok(t, delimiters) != NULL)  
  25.         for (numtokens = 1; strtok(NULL, delimiters)!= NULL; numtokens++);  
  26.   
  27.     if ((*argvp = malloc((numtokens+1)* sizeof ( char  *))) == NULL){  
  28.         error = errno;  
  29.         free(t);  
  30.         errno = error;  
  31.         return  -1;  
  32.     }  
  33.   
  34.     if (numtokens == 0){  
  35.         free(t);  
  36.     }else {  
  37.         strcpy(t, snew);  
  38.         **argvp = strtok(t, delimiters);//注意此处的指针操作   
  39.         for (i = 1;i < numtokens;i++)  
  40.             *((*argvp)+i) = strtok(NULL, delimiters);//注意此处的指针操作   
  41.     }  
  42.           
  43.     *((*argvp)+numtokens) = NULL;  
  44.   
  45.     return  numtokens;  
  46. }  

 

 程序的主体比较简单,就是按照传入的s,按照界定符delimiters对其进行分割,分割完成后将其放在一个二维数组中,第一维表示最后数组,第二维表示第一个数组中每一个元素的值。

测试

好了,我们测试一下其运行情况:

 

C代码
  1. int  main( int  argc,  char  **argv){  
  2.     char  delim[] =  " /t" ;  
  3.     int  i;  
  4.     char  **argvp;  
  5.     int  numtokens;  
  6.     char  *test =  "mine -c 10 2.0" ;  
  7.   
  8.     if ((numtokens = makeargv(test, delim, &argvp)) == -1){  
  9.         fprintf(stderr, "failed to parse the string you given:%s/n" , test);  
  10.         return  1;  
  11.     }  
  12.     printf("argument contains :/n" );  
  13.     for (i = 0;i < numtokens;i++)  
  14.         printf("%d:%s/n" , i, argvp[i]);  
  15.     return  0;  
  16. }  

 

运行结果如下:

C:/development/cpl/usp>ls
Makefile a.exe makeargv.c nbproject

C:/development/cpl/usp>a
argument contains :
0:mine
1:-c
2:10
3:2.0

个人感觉,能把指针用到这种熟练程度,才算是对C掌握了。《UNIX系统编程》中的代码非常优雅,从大二一直读到毕业,毕业后得空还在读。我会尽量陆续把体会贴出来,以供参考。

 

【作者】JavaEye网站的abruzzi

你可能感兴趣的:(编程,c,unix,null,语言,makefile)