空指標有以下三種用法:(1)用空指標終止對遞迴資料結構的間接引用。遞迴是指一個事物由這個事物本身來定義。請看下例: /*Dumb implementation;should use a loop */ unsigned factorial(unsinged i) { if(i=0 || i==1) { return 1; } else { return i * factorial(i-1); } }在上例中,階乘函式factoriai()呼叫了它本身,因此,它是遞迴的。一個遞迴資料結構同樣由它本身來定義。最簡單和最常見的遞迴資料結構是(單向)連結串列,連結串列中的每一個元素都包含一個值和一個指向連結串列中下一個元素的指標。請看下例: struct string_list { char *str; /* string(inthiscase)*/ struct string_list *next; };此外還有雙向連結串列(每個元素還包含一個指向連結串列中前一個元素的指標)、鍵樹和雜湊表等許多整潔的資料結構,一本較好的介紹資料結構的書中都會介紹這些內容。你可以透過指向連結串列中第一個元素的指標開始引用一個連結串列,並透過每一個元素中指向下一個元素的指標不斷地引用下一個元素;在連結串列的最後一個元素中,指向下一個元素的指標被賦值為NULL,當你遇到該空指標時,就可以終止對連結串列的引用了。請看下例: while(p!=NULL) { /*dO something with p->str*/ p=p->next; }請注意,即使p一開始就是一個空指標,上例仍然能正常工作。(2)用空指標作函式呼叫失敗時的返回值。許多C庫函式的返回值是一個指標,在函式呼叫成功時,函式返回一個指向某一物件的指標;反之,則返回一個空指標。請看下例: if(setlocale(cat,loc_p)==NULL) { /* setlocale()failed;do something*/ /* ...*/ }返回值為一指標的函式在呼叫成功時幾乎總是返回一個有效指標(其值不等於零),在呼叫失敗時則總是返回一個空指標(其值等於零);而返回值為一整型值的函式在呼叫成功時幾乎總是返回一個零值,在呼叫失敗時則總是返回一個非零值。請看下例: if(raise(sig)!=0){ /* raise()failed;do something*/ /* ... */ }對上述兩類函式來說,呼叫成功或失敗時的返回值含義都是不同的。另外一些函式在呼叫成功時可能會返回一個正值,在呼叫失敗時可能會返回一個零值或負值。因此,當你使用一個函式之前,應該先看一下它的返回值是哪種型別,這樣你才能判斷函式返回值的含義。(3)用空指標作警戒值 警戒值是標誌事物結尾的一個特定值。例如,main()函式的預定義引數argv是一個指標陣列,它的最後一個元素(argv[argc])永遠是一個空指標,因此,你可以用下述方法快速地引用argv中的每一個元素:/* A simple program that prints all its arguments. It doesn"t use argc ("argument count"); instread. it takes advantage of the fact that the last value in argv ("argument vector") is a null pointer.*/# include <stdio. h># include <assert. h>intmain ( int argc, char * * argv){ int i; printf ("program name = \"%s\"\n", argv[0]); for (i=l; argv[i] !=NULL; ++i) printf ("argv[%d] = \"%s\"\n", i, argv[f]); assert (i = = argc) ; / * see FAQ XI. 5 * / return 0; / * see FAQ XVI. 4 * /}
空指標有以下三種用法:(1)用空指標終止對遞迴資料結構的間接引用。遞迴是指一個事物由這個事物本身來定義。請看下例: /*Dumb implementation;should use a loop */ unsigned factorial(unsinged i) { if(i=0 || i==1) { return 1; } else { return i * factorial(i-1); } }在上例中,階乘函式factoriai()呼叫了它本身,因此,它是遞迴的。一個遞迴資料結構同樣由它本身來定義。最簡單和最常見的遞迴資料結構是(單向)連結串列,連結串列中的每一個元素都包含一個值和一個指向連結串列中下一個元素的指標。請看下例: struct string_list { char *str; /* string(inthiscase)*/ struct string_list *next; };此外還有雙向連結串列(每個元素還包含一個指向連結串列中前一個元素的指標)、鍵樹和雜湊表等許多整潔的資料結構,一本較好的介紹資料結構的書中都會介紹這些內容。你可以透過指向連結串列中第一個元素的指標開始引用一個連結串列,並透過每一個元素中指向下一個元素的指標不斷地引用下一個元素;在連結串列的最後一個元素中,指向下一個元素的指標被賦值為NULL,當你遇到該空指標時,就可以終止對連結串列的引用了。請看下例: while(p!=NULL) { /*dO something with p->str*/ p=p->next; }請注意,即使p一開始就是一個空指標,上例仍然能正常工作。(2)用空指標作函式呼叫失敗時的返回值。許多C庫函式的返回值是一個指標,在函式呼叫成功時,函式返回一個指向某一物件的指標;反之,則返回一個空指標。請看下例: if(setlocale(cat,loc_p)==NULL) { /* setlocale()failed;do something*/ /* ...*/ }返回值為一指標的函式在呼叫成功時幾乎總是返回一個有效指標(其值不等於零),在呼叫失敗時則總是返回一個空指標(其值等於零);而返回值為一整型值的函式在呼叫成功時幾乎總是返回一個零值,在呼叫失敗時則總是返回一個非零值。請看下例: if(raise(sig)!=0){ /* raise()failed;do something*/ /* ... */ }對上述兩類函式來說,呼叫成功或失敗時的返回值含義都是不同的。另外一些函式在呼叫成功時可能會返回一個正值,在呼叫失敗時可能會返回一個零值或負值。因此,當你使用一個函式之前,應該先看一下它的返回值是哪種型別,這樣你才能判斷函式返回值的含義。(3)用空指標作警戒值 警戒值是標誌事物結尾的一個特定值。例如,main()函式的預定義引數argv是一個指標陣列,它的最後一個元素(argv[argc])永遠是一個空指標,因此,你可以用下述方法快速地引用argv中的每一個元素:/* A simple program that prints all its arguments. It doesn"t use argc ("argument count"); instread. it takes advantage of the fact that the last value in argv ("argument vector") is a null pointer.*/# include <stdio. h># include <assert. h>intmain ( int argc, char * * argv){ int i; printf ("program name = \"%s\"\n", argv[0]); for (i=l; argv[i] !=NULL; ++i) printf ("argv[%d] = \"%s\"\n", i, argv[f]); assert (i = = argc) ; / * see FAQ XI. 5 * / return 0; / * see FAQ XVI. 4 * /}