午夜网站国产欧美_加勒比视频亚洲无码_91亚洲人人在字幕国产_18禁止美女爆乳免费网站_被消防员c哭高h野外糙汉动漫_午夜精品视频在线无码_gogowww人体大胆裸体午液_2021自拍偷区亚洲综合第一页_国产欧美一区二区精品性色超碰_99國產精品無碼

Hi,您好,歡迎來(lái)到西安盛圖軟件科技有限公司!

C語(yǔ)言實(shí)現(xiàn)泛型編程

發(fā)布時(shí)間:2023-06-20 10:50:55

泛型編程讓你編寫完全一般化并可重復(fù)使用的算法,其效率與針對(duì)某特定數(shù)據(jù)類型而設(shè)計(jì)的算法相同。在 C 語(yǔ)言中,可以通過(guò)一些手段實(shí)現(xiàn)這樣的泛型編程。這里介紹一種方法——通過(guò)無(wú)類型指針 void*。

看下面的一個(gè)實(shí)現(xiàn)交換兩個(gè)元素內(nèi)容的函數(shù) swap,以整型 int 為例:

void swap(int* i1,int* i2){  
         int temp;  
         temp = *i1;  
         *i1 = *i2;  
         *i2 = temp;  }

當(dāng)你想交換兩個(gè) char 類型時(shí),你還得重寫一個(gè)參數(shù)類型為 char 的函數(shù),是不是能用無(wú)類型的指針來(lái)作為參數(shù)呢?看如下改動(dòng):

void swap(void *vp1,void *vp2){  
       void temp = *vp1;  
       *vp1 = *vp2;  
       *vp2 = temp;  }

這段代碼是錯(cuò)誤的,是通不過(guò)編譯的。首先,變量是不能聲明為 void 無(wú)類型的。而你不知道調(diào)用此函數(shù)傳進(jìn)的參數(shù)是什么類型的,無(wú)法確定一種類型的聲明。同時(shí),不能將 * 用在無(wú)類型指針上,因?yàn)橄到y(tǒng)沒(méi)有此地址指向?qū)ο蟠笮〉男畔?。在編譯階段,編譯器無(wú)法得知傳入此函數(shù)參數(shù)的類型的。這里要想實(shí)現(xiàn)泛型的函數(shù),需要在調(diào)用的地方傳入相關(guān)要交換的對(duì)象的地址空間大小 size,同時(shí)利用在頭文件 string.h 中定義的 memcpy() 函數(shù)來(lái)實(shí)現(xiàn)。改動(dòng)如下:

void swap(void *vp1,void *vp2,int size){  
      char buffer[size];//注意此處gcc編譯器是允許這樣聲明的
      memcpy(buffer,vp1,size);  
      memcpy(vp1,vp2,size);  
      memcpy(vp2,buffer,size);  }

在調(diào)用這個(gè)函數(shù)時(shí),可以像如下這樣調(diào)用(同樣適用于其它類型的 x、y):

int x = 27,y = 2;  swap(&x,&y,sizeof(int));

下面看另一種功能的函數(shù):

int lsearch(int key,int array[],int size){
      for(int i = 0;i < size; ++i)
                  if(array[i] == key)
                           return i;
     return -1;}

此函數(shù)在數(shù)組 array 中查找 key元素,找到后返回它的索引,找不到返回 -1。

如上,也可以實(shí)現(xiàn)泛型的函數(shù):

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;}

代碼第三行:將數(shù)組的首地址強(qiáng)制轉(zhuǎn)換為指向 char 類型的指針,是利用 char 類型大小為1字節(jié)的特性,使 elemAddr 指向此"泛型"數(shù)組的第 i-1 個(gè)元素的首地址。因?yàn)橹耙呀?jīng)說(shuō)過(guò),此時(shí)你并不知道你傳入的是什么類型的數(shù)據(jù),系統(tǒng)無(wú)法確定此數(shù)組一個(gè)元素有多長(zhǎng),跳向下個(gè)元素需要多少字節(jié),所以強(qiáng)制轉(zhuǎn)換為指向 char 的指針,再加上參數(shù)傳入的元素大小信息和累加數(shù)i的乘積,即偏移地址,即可得此數(shù)組第 i-1 個(gè)元素的首地址。這樣使無(wú)論傳入的參數(shù)是指向什么類型的指針,都可以得到指向正確元素的指針,實(shí)現(xiàn)泛型編程。

函數(shù) memcmp() 原型:int memcmp(void *dest,const void *src,int n),比較兩段長(zhǎng)度為n首地址分別為 dest、src 的地址空間中的內(nèi)容。

此函數(shù)在數(shù)組 base 中查找 key 元素,找到則返回它的地址信息,找不到則返回 NULL。

如果使用函數(shù)指針,則可以實(shí)現(xiàn)其行為的泛型:

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;}

再定義一個(gè)要調(diào)用的函數(shù):

int intCmp(void* elem1,void* elem2){
        int* ip1 = elem1;
        int* ip2 = elem2;
        return *ip1-*ip2;}

看如下調(diào)用:

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 語(yǔ)言也可以實(shí)現(xiàn)一定的泛型編程,但這樣是不安全的,系統(tǒng)對(duì)其只有有限的檢查。在編程時(shí)一定要多加細(xì)心。


上一篇:干貨分享|C錯(cuò)誤處理
下一篇:2023年成為程序員還有發(fā)展前景嗎?

歡迎登錄盛圖科技

歡迎注冊(cè)盛圖科技

已有賬號(hào),立即登錄