C language generic programming examples tutorial

  • 2020-04-02 02:42:11
  • OfStack

This article illustrates the method of generic programming in C language, and shares it with you for your reference. Specific analysis is as follows:

First, generic programming lets you write completely generic and reusable algorithms that are as efficient as algorithms designed for a particular data type. In C, there are several ways to achieve such generic programming. Here is a method called void* with an untyped pointer

Look at the following function swap to exchange the contents of two elements, take int as an example:


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

When you want to swap two char types, you also have to override a function whose argument type is char. Can you use an untyped pointer as an argument? See the following changes:


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

But this code is wrong and will not compile. First, a variable cannot be declared void untyped. You do not know what type of argument is passed in to call this function, and you cannot determine the declaration of a type. Also, you cannot use * on untyped Pointers, because the system does not have this address to point to the size of the object. At compile time, the compiler cannot know the type of the function parameter passed in. To implement a generic function here, you need to pass in the size of the address space of the object to be exchanged where it is called, using the memcpy() function defined in the header file string.h. The changes are as follows:


void swap(void *vp1,void *vp2,int size){ 
   char buffer[size];//Note that the GCC compiler allows this declaration here
   memcpy(buffer,vp1,size); 
   memcpy(vp1,vp2,size); 
   memcpy(vp2,buffer,size); 
} 

When this function is called, it can be called as follows (also for other types of x and y) :


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

Now let's look at the function of another function:


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

This function looks for the key element in the array, returns its index, and fails to return -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;
}

Line 3: cast the first address of the array to a pointer to the char type, which takes advantage of the 1-byte size of the char type to make elemAddr point to the first address of the i-1st element of this "generic" array. Because have said before, now you don't know you to what type of data, system can not be sure how long is this array an element, jump down a elements need how many bytes, so cast to pointer to char, coupled with the parameters of the incoming element size information and the accumulative number of the product, I offset, brings the array element I - 1 first address. In this way, no matter what type of pointer the parameter is passed in, the pointer to the correct element can be obtained, achieving generic programming.

Function memcmp() prototype: int memcmp(void *dest,const void * SRC,int n), compares the contents of the address space of two segments of length n whose first address is dest and SRC.

This function looks for the key element in the array base, returns its address information if it is found, and returns NULL if it is not found.

If you use a function pointer, you can implement a generic type of its behavior:


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

Define another function to call:


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

See the following call:


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("NOn");
else
     printf("YESn");

C language can also achieve a certain amount of generic programming, but this is not secure, the system has only a limited check on it. Be careful in your programming.

I believe that this paper has a certain reference value to the study of C programming.


Related articles: