淺談C語言中的多級(jí)指針
最近看《UNIX系統(tǒng)編程》,感覺能把C語言用到這個(gè)水平,才能算是登堂入室。
一般來說,我們會(huì)把指針跟數(shù)組聯(lián)系起來理解,比如*p就是一個(gè)一維數(shù)組,**p是兩維數(shù)組等,而一般而言,見到兩維的指針也算是難得了,更高維的只怕看一會(huì)就會(huì)暈掉?!禪NIX系統(tǒng)編程》中有個(gè)關(guān)于參數(shù)列表的例子,感覺對(duì)指針運(yùn)用的已經(jīng)到出神入化的境地,所以貼出來大家參考一下。
指向指針的多級(jí)指針
在C語言的入口main函數(shù)中,有一個(gè)**argv參數(shù),指明命令行參數(shù),一般寫法是這樣:
C代碼
- int main(int argc, char **argv){
- /*
- * code here.
- */
- }
- int main(int argc, char **argv){
- /*
- * code here.
- */
- }
這個(gè)**argv,是一個(gè)指向指針的指針,用來將命令行參數(shù)保存下來,比如,輸入一條命令:
prog -c -v 200
**argv中的內(nèi)容即為 prog, -c, -v, 200. 因?yàn)閜rog, -c等的長(zhǎng)度不等,就需要一個(gè)指針來引用他們,而prog后邊接幾個(gè)參數(shù)也是不定的,所以有需要有一個(gè)指針來引用,所以就是這里的二維指針了。畫一個(gè)table可能看起來比較清晰一些:
prog |
-c |
-v |
200 |
再考慮這樣一種情況,shell程序,對(duì)于你會(huì)輸多少行命令也是不知道的,那它就需要再多一個(gè)指針來引用你會(huì)有多少個(gè)命令輸入。這就是我們今天要看的(***ptr)了。
指向"指針的指針"的多級(jí)指針
書中的例子是這樣,先看下函數(shù)的原型:
C代碼
- int makeargv(const char *s, const char *delimiters, char ***argvp);
- int makeargv(const char *s, const char *delimiters, char ***argvp);
函數(shù)接受三個(gè)參數(shù),第一個(gè)是要分析的串,第二個(gè)是界定符序列,第三個(gè)是生成的"指針的指針"(即二維數(shù)組)的指針。實(shí)現(xiàn)比較簡(jiǎn)單,主要是看其中關(guān)于指針的用法:
C代碼
- /*
- * author : juntao.qiu
- */
- int makeargv(const char *s, const char *delimiters, char ***argvp){
- int error;
- int i;
- int numtokens;
- const char *snew;
- char *t;
- if((s == NULL) || (delimiters == NULL) || (argvp == NULL)){
- error = EINVAL;
- return -1;
- }
- *argvp = NULL;
- ssnew = s + strspn(s, delimiters);
- if((t = malloc(strlen(snew)+1)) == NULL)
- return -1;
- strcpy(t, snew);
- numtokens = 0;
- if(strtok(t, delimiters) != NULL)
- for(numtokens = 1; strtok(NULL, delimiters)!= NULL; numtokens++);
- if((*argvp = malloc((numtokens+1)*sizeof(char *))) == NULL){
- error = errno;
- free(t);
- errno = error;
- return -1;
- }
- if(numtokens == 0){
- free(t);
- }else{
- strcpy(t, snew);
- **argvp = strtok(t, delimiters);//注意此處的指針操作
- for(i = 1;i < numtokens;i++)
- *((*argvp)+i) = strtok(NULL, delimiters);//注意此處的指針操作
- }
- *((*argvp)+numtokens) = NULL;
- return numtokens;
- }
- /*
- * author : juntao.qiu
- */
- int makeargv(const char *s, const char *delimiters, char ***argvp){
- int error;
- int i;
- int numtokens;
- const char *snew;
- char *t;
- if((s == NULL) || (delimiters == NULL) || (argvp == NULL)){
- error = EINVAL;
- return -1;
- }
- *argvp = NULL;
- ssnew = s + strspn(s, delimiters);
- if((t = malloc(strlen(snew)+1)) == NULL)
- return -1;
- strcpy(t, snew);
- numtokens = 0;
- if(strtok(t, delimiters) != NULL)
- for(numtokens = 1; strtok(NULL, delimiters)!= NULL; numtokens++);
- if((*argvp = malloc((numtokens+1)*sizeof(char *))) == NULL){
- error = errno;
- free(t);
- errno = error;
- return -1;
- }
- if(numtokens == 0){
- free(t);
- }else{
- strcpy(t, snew);
- **argvp = strtok(t, delimiters);//注意此處的指針操作
- for(i = 1;i < numtokens;i++)
- *((*argvp)+i) = strtok(NULL, delimiters);//注意此處的指針操作
- }
- *((*argvp)+numtokens) = NULL;
- return numtokens;
- }
程序的主體比較簡(jiǎn)單,就是按照傳入的s,按照界定符delimiters對(duì)其進(jìn)行分割,分割完成后將其放在一個(gè)二維數(shù)組中,第一維表示最后數(shù)組,第二維表示第一個(gè)數(shù)組中每一個(gè)元素的值。
測(cè)試
好了,我們測(cè)試一下其運(yùn)行情況:
C代碼
- int main(int argc, char **argv){
- char delim[] = " \t";
- int i;
- char **argvp;
- int numtokens;
- char *test = "mine -c 10 2.0";
- if((numtokens = makeargv(test, delim, &argvp)) == -1){
- fprintf(stderr, "failed to parse the string you given:%s\n", test);
- return 1;
- }
- printf("argument contains :\n");
- for(i = 0;i < numtokens;i++)
- printf("%d:%s\n", i, argvp[i]);
- return 0;
- }
- int main(int argc, char **argv){
- char delim[] = " \t";
- int i;
- char **argvp;
- int numtokens;
- char *test = "mine -c 10 2.0";
- if((numtokens = makeargv(test, delim, &argvp)) == -1){
- fprintf(stderr, "failed to parse the string you given:%s\n", test);
- return 1;
- }
- printf("argument contains :\n");
- for(i = 0;i < numtokens;i++)
- printf("%d:%s\n", i, argvp[i]);
- return 0;
- }
運(yùn)行結(jié)果如下:
- 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
個(gè)人感覺,能把指多級(jí)指針用到這種熟練程度,才算是對(duì)C掌握了?!禪NIX系統(tǒng)編程》中的代碼非常優(yōu)雅,從大二一直讀到畢業(yè),畢業(yè)后得空還在讀。我會(huì)盡量陸續(xù)把體會(huì)貼出來,以供參考。
【編輯推薦】