#include iostream
創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)和成都服務(wù)器托管的網(wǎng)絡(luò)公司,有著豐富的建站經(jīng)驗(yàn)和案例。
using namespace std;
templatetypename T
T Mam(T *_itBegin, T *_itEnd)
{
T *_val = _itBegin;
for (T *_it = _itBegin; _it!=_itEnd; ++_it)
if(*_it *_val)
_val = _it;
return (*_val);
}int main()
{
char pArray[] = "oasndflwerasdf";
coutMam(pArray, pArray+sizeof(pArray)/sizeof(char))endl;
int pArray1[] = {7,8,9,1,3,4,7,65,58};
coutMam(pArray1, pArray1+sizeof(pArray1)/sizeof(int))endl;
return 0;
}
如果要寫個(gè)函數(shù)支持多種數(shù)據(jù)類型,首先想到的就是C++的模板了,但是有時(shí)候只能用C語(yǔ)言,比如在linux內(nèi)核開(kāi)發(fā)中,為了減少代碼量,或者是某面試官的要求…
考慮了一陣子后,就想到了qsort上.qsort的函數(shù)原型:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
快排時(shí),只要自己實(shí)現(xiàn)相應(yīng)數(shù)據(jù)類型的比較函數(shù)cmpare就可以了.如果比較int型時(shí),一個(gè)典型的compare函數(shù)如下:
那么,就是說(shuō)可以利用void *. void *意指未指定類型,也可以理解為任意類型。其他類型的指針可以直接賦值給void *變量,但是void *變量需要強(qiáng)制類型轉(zhuǎn)換為其它指針類型。這個(gè)相信大家都知道。那么下面以一個(gè)簡(jiǎn)單的題目為例,來(lái)探討如何在C語(yǔ)言中實(shí)現(xiàn)模板函數(shù)。
方法1: 利用void *.
在看下面的源程序之前,需要了解幾點(diǎn)。首先,在32位平臺(tái)上,任何類型的指針?biāo)嫉淖止?jié)都是4個(gè)字節(jié),因?yàn)?2位機(jī)器虛擬內(nèi)存一般為4G,即2的32次方,只要32位即4個(gè)字節(jié)就可以足夠?qū)ぶ?,sizeof(void *)=4; 其次,雖然各種不同類型的指針?biāo)嫉目臻g都為4個(gè)字節(jié),但是不同類型的指針?biāo)傅目臻g的字節(jié)數(shù)卻不同(這一點(diǎn)尤為重要,下面的程序我在開(kāi)始沒(méi)有調(diào)通就因?yàn)檫@點(diǎn)意識(shí)不強(qiáng))。所以,如果你將一個(gè)指針強(qiáng)制轉(zhuǎn)換為另一個(gè)類型的指針,指針本身所占的字節(jié)是不變的,但是,如果對(duì)這個(gè)指針進(jìn)行運(yùn)算,比如 *p,p++,p-=1等一般都是不同的。 再次,函數(shù)指針應(yīng)該了解下,這里不多說(shuō)。 最后,因?yàn)镾andy跟我說(shuō),C++開(kāi)始的時(shí)候模板的實(shí)現(xiàn)其實(shí)就是利用宏替換,在編譯的時(shí)候確定類型。所以,為了方便,類型也用了預(yù)編譯指令#define。
span#include?"stdio.h"/span
span#include?"stdlib.h"/span
span//typedef?int?T;??//或者下面的也可以./span
span#define??T?int/span
//這個(gè)FindMin是Sandy寫的.felix021也寫了個(gè),差不多的就不貼出來(lái)的.
void?FindMin(const?void??*arr,int?arr_size,int?arrmembersize,int?*index,
int?(*cmp)(const?void?*,const?void?*b)){
int?i;
*index=0;
char?*p=(char?*)arr;
char?*tmp=p;
for?(i=1;iarr_size?;i++){
if?(cmp(tmp,p)0){
tmp=p;
}
p+=arrmembersize;
}
(*index)=((int)(tmp-arr))/arrmembersize;
}
*//span
可以把指針看作是char?*,如果轉(zhuǎn)換為int?*,那下面的位移就不正確了./span
indexspan=/spanispan;/span
span}/span
span}/span
spanreturn/span?indexspan;/span
span}/span
spanint/span?resultspan;/spanspan//result保存的是最小值索引./span
resultspan=/spanFindMinspan(/spanarr,span12/span,
首先,C沒(méi)有函數(shù)模版。C++才有。
其次,template class T是函數(shù)聲明的一部分,所以下面函數(shù)實(shí)現(xiàn)應(yīng)該是:
template class T
void swap(T a,T b){
int temp;
temp=a;
a=b;
b=temp;
}
最后,#include iostream,在標(biāo)準(zhǔn)的C++函數(shù)中,std的域中已經(jīng)有一個(gè)swap函數(shù)。
而且前面也using namespace了。函數(shù)聲明重復(fù)。
兩個(gè)辦法:
1 swap(i,j);改為 ::swap(i,j); //全局化。
2 swap改個(gè)名字。
C語(yǔ)言中有模板函數(shù)嗎? 模板不是c++中才提供的特性的嘛,大部分函數(shù)都是自定義函數(shù)。沒(méi)有什么優(yōu)點(diǎn)或者缺點(diǎn)吧,完全看函數(shù)自身的功能
這些都是C++的玩意
T min( T (arr)[size] ); //T (arr)[size] arr是個(gè)數(shù)組的引用, 如果去掉括號(hào),就變成引用的數(shù)組,而引用的數(shù)組是不存在的,改成T*就成了第二種定義了
用引用當(dāng)參數(shù),比如min(a),a就是實(shí)參本身,而不是副本,這是C語(yǔ)言所沒(méi)有的特性. 既然是實(shí)參本身,那么數(shù)組a就不會(huì)退化為指針,也就是說(shuō),編譯器可以可以獲得a的大小,所以size就不需要提供了
而第一種和第二種,arr退化為指針了,所以必須通過(guò)其他途徑提供數(shù)組長(zhǎng)度,