C語言如何實現泛型程式設計?
這裡介紹一種方法——透過無型別指標 void*。
看下面的一個實現交換兩個元素內容的函式 swap,以整型 int 為例:
void swap(int* i1,int* i2){ int temp; temp = *i1; *i1 = *i2; *i2 = temp; }
當你想交換兩個 char 型別時,你還得重寫一個引數型別為 char 的函式,是不是能用無型別的指標來作為引數呢?看如下改動:
void swap(void *vp1,void *vp2){ void temp = *vp1; *vp1 = *vp2; *vp2 = temp; }
這段程式碼是錯誤的,是通不過編譯的。首先,變數是不能宣告為 void 無型別的。而你不知道呼叫此函式傳進的引數是什麼型別的,無法確定一種型別的宣告。同時,不能將 * 用在無型別指標上,因為系統沒有此地址指向物件大小的資訊。在編譯階段,編譯器無法得知傳入此函式引數的型別的。這裡要想實現泛型的函式,需要在呼叫的地方傳入相關要交換的物件的地址空間大小 size,同時利用在標頭檔案 string.h 中定義的 memcpy() 函式來實現。改動如下:
void swap(void *vp1,void *vp2,int size){ char buffer[size];//注意此處gcc編譯器是允許這樣宣告的 memcpy(buffer,vp1,size); memcpy(vp1,vp2,size); memcpy(vp2,buffer,size); }
在呼叫這個函式時,可以像如下這樣呼叫(同樣適用於其它型別的 x、y):
int x = 27,y = 2; swap(&x,&y,sizeof(int));
下面看另一種功能的函式:
int lsearch(int key,int array[],int size){ for(int i = 0;i < size; ++i) if(array[i] == key) return i; return -1; }
此函式在陣列 array 中查詢 key元素,找到後返回它的索引,找不到返回 -1。
如上,也可以實現泛型的函式:
void* lsearch(void* key, void *base, int n, int elemSize){ for(int i = 0;i < n; ++i){ void *elemAddr = (char *)base+i*elemSize; if(memcmp(key, elemAddr, elemSize) == 0) return elemAddr; } return NULL; }
程式碼第三行:將陣列的首地址強制轉換為指向 char 型別的指標,是利用 char 型別大小為1位元組的特性,使 elemAddr 指向此"泛型"陣列的第 i-1 個元素的首地址。因為之前已經說過,此時你並不知道你傳入的是什麼型別的資料,系統無法確定此陣列一個元素有多長,跳向下個元素需要多少位元組,所以強制轉換為指向 char 的指標,再加上引數傳入的元素大小資訊和累加數i的乘積,即偏移地址,即可得此陣列第 i-1 個元素的首地址。這樣使無論傳入的引數是指向什麼型別的指標,都可以得到指向正確元素的指標,實現泛型程式設計。
函式 memcmp() 原型:int memcmp(void *dest,const void *src,int n),比較兩段長度為n首地址分別為 dest、src 的地址空間中的內容。
此函式在陣列 base 中查詢 key 元素,找到則返回它的地址資訊,找不到則返回 NULL。
如果使用函式指標,則可以實現其行為的泛型:
void *lsearch(void *key,void *base,int n,int elemSize,int(*cmpfn)(void*,void*,int)){ for(int i = 0;i < n; ++i){ void *elemAddr = (char *)base+i*elemSize; if(cmpfn(key,elemAddr,elemSize) == 0) return elemAddr; } return NULL; }
再定義一個要呼叫的函式:
int intCmp(void* elem1,void* elem2){ int* ip1 = elem1; int* ip2 = elem2; return *ip1-*ip2; }
看如下呼叫:
int array[] = {1,2,3,4,5,6}; int size = 6; int number = 3; int *found = lsearch(&number,array,size,sizeof(int),intCmp); if(found == NULL) printf("NO\n"); else printf("YES\n");
C 語言也可以實現一定的泛型程式設計,但這樣是不安全的,系統對其只有有限的檢查。在程式設計時一定要多加細心。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901823/viewspace-2766776/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在C語言中實現泛型程式設計C語言泛型程式設計
- GO語言泛型程式設計實踐Go泛型程式設計
- C 語言實現泛型 swap 函式泛型函式
- 使用 Go 泛型的函數語言程式設計Go泛型函數程式設計
- 泛型程式設計在非C++語言中的實現之探討 (轉)泛型程式設計C++
- C++ 簡單實現陣列類泛型程式設計示例C++陣列泛型程式設計
- 泛型最佳實踐:Go泛型設計者教你如何用泛型泛型Go
- c++ 泛型程式設計 之 TypeListsC++泛型程式設計
- C語言程式設計C語言程式設計
- c++ 泛型 程式設計 之 Functor 設計模式C++泛型程式設計設計模式
- 泛型程式設計泛型程式設計
- C語言程式設計原理C語言程式設計
- c語言程式設計題C語言程式設計
- C語言實現繼承多型C語言繼承多型
- java 泛型程式設計Java泛型程式設計
- c語言程式設計--實驗報告一C語言程式設計
- c語言程式設計——實驗報告六C語言程式設計
- # c語言程式設計——實驗報告一C語言程式設計
- c語言程式設計——實驗報告一C語言程式設計
- c語言程式設計——實驗報告二C語言程式設計
- C語言程式設計—實驗報告四C語言程式設計
- C語言程式設計-實驗報告4C語言程式設計
- 用C語言實現有限狀態機--讀《C專家程式設計》C語言程式設計
- 真的可以,用C語言實現物件導向程式設計OOPC語言物件程式設計OOP
- C++ primer 模板與泛型程式設計C++泛型程式設計
- 【C/C++學院】(23)Mysql資料庫程式設計–C語言程式設計實現mysql客戶端C++MySql資料庫程式設計C語言客戶端
- C語言MySQL程式設計示例C語言MySql程式設計
- C 語言程式設計(unix) (轉)程式設計
- 結對程式設計(c語言)程式設計C語言
- c++ 泛型程式設計 之 自動生成程式碼C++泛型程式設計
- C語言/C++程式設計學習:棧的程式碼實現之陣列方案C語言C++程式設計陣列
- OOC 物件導向 C 語言程式設計實踐物件程式設計
- 挑戰程式設計技能 Rust 語言實現程式設計Rust
- DDD的函數語言程式設計實現函數程式設計
- C語言程式設計入門之--第四章C語言基本資料型別C語言程式設計資料型別
- C++ 泛型程式設計基礎:模板通識C++泛型程式設計
- 十、GO程式設計模式 : 泛型程式設計Go程式設計設計模式泛型
- 奇怪的C語言——C51程式設計C語言注意事項C語言程式設計