如果要寫個函式支援多種資料型別,首先想到的就是c++的模板了,但是有時候只能用c語言,比如在linux核心開發中,為了減少**量,或者是某面試官的要求…
考慮了一陣子後,就想到了qsort上.qsort的函式原型:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
快排時,只要自己實現相應資料型別的比較函式cmpare就可以了.如果比較int型時,乙個典型的compare函式如下:
int cmp(const void *a,const void *b)
那麼,就是說可以利用void *. void *意指未指定型別,也可以理解為任意型別。其他型別的指標可以直接賦值給void *變數,但是void *變數需要強制型別轉換為其它指標型別。這個相信大家都知道。那麼下面以乙個簡單的題目為例,來**如何在c語言中實現模板函式。
方法1: 利用void *.
在看下面的源程式之前,需要了解幾點。首先,在32位平台上,任何型別的指標所佔的位元組都是4個位元組,因為32位機器虛擬記憶體一般為4g,即2的32次方,只要32位即4個位元組就可以足夠定址,sizeof(void *)=4; 其次,雖然各種不同型別的指標所佔的空間都為4個位元組,但是不同型別的指標所指的空間的位元組數卻不同(這一點尤為重要,下面的程式我在開始沒有調通就因為這點意識不強)。所以,如果你將乙個指標強制轉換為另乙個型別的指標,指標本身所佔的位元組是不變的,但是,如果對這個指標進行運算,比如 *p,p++,p-=1等一般都是不同的。 再次,函式指標應該了解下,這裡不多說。 最後,因為sandy跟我說,c++開始的時候模板的實現其實就是利用巨集替換,在編譯的時候確定型別。所以,為了方便,型別也用了預編譯指令#define。
#include "stdio.h"
#include "stdlib.h"
//typedef int t; //或者下面的也可以.
#define t int
int cmp(const void *a,const void *b)
/*//這個findmin是sandy寫的.felix021也寫了個,差不多的就不貼出來的.
void findmin(const void *arr,int arr_size,int arrmembersize,int *index,
int (*cmp)(const void *,const void *b))
p+=arrmembersize;
}(*index)=((int)(tmp-arr))/arrmembersize;}*/
int findmin(const void *arr,int arr_size,int arrmembersize,int (*cmp)(const void *,const void *)) }
return index;}
int main();
//int *result;
int result;//result儲存的是最小值索引.
result=findmin(arr,12,sizeof(arr[0]),cmp);
printf("%d,%d
",result,arr[result]);
system("pause");
return 0;
}
方法2:利用巨集。在編譯的時候確定型別。查閱資料的時候,很多都說這種方法比較好,方便除錯,也很直觀,雖然很囉嗦。
#include #ifndef _int_
#define _int_
#endif
int cmp(const void *a,const void *b)
#ifdef _int_
void findmin(int *arr,int arr_size,int *result,int cmp(const void *a,const void *b))
#elif _float_
void findmin(float *arr,int arr_size,float *result,int cmp(const void *a,const void *b))
#elif _double_
void findmin(double *arr,int arr_size,double *result,int cmp(const void *a,const void *b))
#endif}
int main();
int result;
findmin(arr1,6,&result,cmp);
printf("%d
",result);
return 0;
}
方法3:在findmin中,不用強制型別轉換為char *,直接利用memcpy記憶體拷貝過去,這時,還可以在引數列表中儲存結果,而不是索引。此方法由csdn上的ltc_mouse提供。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void findmin(void *arr,int arr_size,int arrmembersize,void * result,
int (*fpcmp)(const void *,const void *b))
}}int cmp_int(const void *a, const void *b)
int cmp_double(const void *a, const void *b)
int main()
; double farr=;
int imin;
double fmin;
findmin( (void *)iarr, sizeof(iarr)/sizeof(iarr[0]), sizeof(iarr[0]), (void *)&imin, cmp_int );
findmin( (void *)farr, sizeof(farr)/sizeof(farr[0]), sizeof(farr[0]), (void *)&fmin, cmp_double);
printf("min of iarr is %d
", imin);
printf("min of farr is %lf
", fmin);
return 0;
}
C 語言中的模板 函式模板
模板概述 c 提供了函式模板 function template.所謂函式模板,實際上是建立乙個通用函式,其函式型別和形參型別不具體制定,用乙個虛擬的型別來代表。這個通用函式 就成為函式模板。凡是函式體相同的函式都可以用這個模板代替,不必定義多個函 數,只需在模板中定義一次即可。在呼叫函式時系統會根...
C語言中scanf 函式的小結
1.scanf 的返回值 scanf函式是有返回值的,接受乙個變數返回1。如 c scanf d d a,b 若輸入的全是整數,則c為2 若全是字元,則c為0 因為scanf在佔位符存在的情況下,只接受符合佔位符的資料。2.scanf的結束 如果不是 c,則以空格,回車,tab鍵結束,或非法字元結束...
C語言中malloc函式實現
該實現使用大容量的靜態陣列作為堆,但也可使用作業系統呼叫分配堆。定義了乙個資料型別header儲存每個儲存器塊的簿記資訊,定義了具有header型別元素的堆陣列,這樣就可以很容易地將簿記資訊儲存在儲存器塊中。型別header包含了3塊資訊 指向列表的下乙個塊的指標,當前分配空間的長度,後面的自由空間...