原函式是《The C programint language 》5.11文字行排序的程式,如下:
void qsort(void *v[], int left, int right, int (*comp)(void *,void *))
{
int i,last;
if( left >= right)
return;
swap(v,left,(left+right)/2);
last = left;
for(i = left + 1; i <= right; ++i)
if(comp(v[i],v[left]) < 0)
swap(v,++last,i);
swap(v,left,last);
qqsort(v,left,last-1,comp);
qqsort(v,last+1,right,comp);
}
該函式有以下特點:
1. 引數 void *v[] ,這是把main函式傳遞的實參轉換為通用的void * * 型別的形參,那對於實參的需要自己強制轉換,比如把 char * lineptr[] 傳遞給 v,必須這樣(void ** )lineptr,
那為什麼能這樣轉化
1. 任意的型別都可以賦給相應的void型別的
2. 該void的型別也可以強制轉換為該型別
那為什麼要這樣轉換
1. 這樣轉換可以滿足函式通用性的要求,任何型別都可以轉換為相應的void型別,相對於這個程式,把char 轉換為 void,只要在comp模型中提供了comp(char *,char *)去呼叫,就把void 轉換為 char 型別進行運算,符合程式通用化的要求;
2. 之所以可以用void的1階以上指標,是因為各種型別的地址位元組都是固定了,win32用4個位元組表示指標,所以只要該函式內的void型別的運算都是對地址的運算都可以,不能對相應的void的型別進行四則和取值運算,因為它雖然指向對應變數的首地址,但是他不知道該地址指向的資料型別,所以除了地址運算其他的都不能進行,也就是說使用這種轉換函式,必須保證該函式內除了地址運算外,不能進行其他的運算。
還有對於 形參void * v [] 去代替實參 (void **)lineptr,對於一個指向void * 的陣列來說,之所以行,是因為v[1]是可以計算,陣列中存的都是指標,固定4個位元組,v[1] 的地址 v + 4就行了,由因為它指向的是地址,v[1]指向一個地址,改地址又是4個位元組的大小,只有這些是可以確定,其他的不行,不能對v[1][1],因為v[1]是個地址,但是這個地址指向的內容的型別不能判定,不知道把改地址指向的那塊資料取幾個位元組,轉換什麼型別,都不得而知。
還有個強制轉換問題:
char s[3][3];
void ** p = s;
把p轉換為s的 ((char (*)[3])p)[0] = s[0]
完整的程式見:http://blog.csdn.net/chenyiming_1990/article/details/9382177