通過qsort(void * lineptr[], int left, int rifht, int (*comp)(void *, void *))解讀指標函式和void指標...

weixin_34126215發表於2013-07-22

原函式是《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

 

 

相關文章