原函數是《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,spa
那爲何能這樣轉化 .net
1. 任意的類型均可以賦給相應的void類型的 指針
2. 該void的類型也能夠強制轉換爲該類型code
那爲何要這樣轉換 blog
1. 這樣轉換能夠知足函數通用性的要求,任何類型均可以轉換爲相應的void類型,相對於這個程序,把char 轉換爲 void,只要在comp模型中提供了comp(char *,char *)去調用,就把void 轉換爲 char 類型進行運算,符合程序通用化的要求;排序
2. 之因此能夠用void的1階以上指針,是由於各類類型的地址字節都是固定了,win32用4個字節表示指針,因此只要該函數內的void類型的運算都是對地址的運算均可以,不能對相應的void的類型進行四則和取值運算,由於它雖然指向對應變量的首地址,可是他不知道該地址指向的數據類型,因此除了地址運算其餘的都不能進行,也就是說使用這種轉換函數,必須保證該函數內除了地址運算外,不能進行其餘的運算。get
還有對於 形參void * v [] 去代替實參 (void **)lineptr,對於一個指向void * 的數組來講,之因此行,是由於v[1]是能夠計算,數組中存的都是指針,固定4個字節,v[1] 的地址 v + 4就好了,由由於它指向的是地址,v[1]指向一個地址,改地址又是4個字節的大小,只有這些是能夠肯定,其餘的不行,不能對v[1][1],由於v[1]是個地址,可是這個地址指向的內容的類型不能斷定,不知道把改地址指向的那塊數據取幾個字節,轉換什麼類型,都不得而知。 ast
還有個強制轉換問題:
char s[3][3];
void ** p = s;
把p轉換爲s的 ((char (*)[3])p)[0] = s[0]
完整的程序見:http://blog.csdn.net/chenyiming_1990/article/details/9382177