How to implement simple generic programming in C Language (1)

Source: Internet
Author: User
Digress

I recently attended Stanford University's Open Course "Programming paradigm Programming Paradigms" at home.

Attached resources of verycd:

Http://www.verycd.com/topics/2838268/

This course is taught in English, but there are still no Chinese or English subtitles. The course is very good. Here, Lecture 4 describes a method to implement generic programming in C language without using a template in C ++. After summing up its notes here, I joined some of my own ideas and experiments and wrote this article to share some experiences with you.

Question

Generic programming allows you to write fully generalized and reusable algorithms, with the same efficiency as the algorithms designed for a specific data type. The so-called generic refers to the meaning that can be operated on multiple data types. C ++ uses parameterized types to implement generic containers. For example, Java introduces the concept of single inheritance. More familiar to you than generics are STL, Standard template library, and Standard template library. STL is an efficient, generic, and interactive software component. STL is a Generic Algorithm Library Based on Iterators and Containers. The existence of Containers makes these Algorithms available for operation. STL contains various generic algorithms (algorithms), generic pointers (iterators), generic containers (containers), and function objects (function objects ).
Objects ). STL is not just a collection of useful components. It is a formal and structured architecture that describes the abstract requirements of software components.

In C language, such generic programming can also be implemented through some means. For example, Macro. Here we will talk about another method-through the void without a type pointer *.

Let's take a look at the following swap function that implements the exchange of two elements. An integer int is used as an example.

Void swap (int * I1, int * I2) {<br/> int temp; <br/> temp = * I1; <br/> * I1 = * I2; <br/> * I2 = temp; <br/>} 

When you want to exchange two char Types, You have to rewrite a function whose parameter type is char. How much do you miss using the template in C ++. Wait, can I use a non-type pointer as a parameter? See the following changes:

Void swap; <br/> * ALB = temp; <br/>} 

This piece of code is incorrect and cannot be compiled. First, the variable cannot be declared as void of no type. However, you do not know the type of parameters passed in by calling this function, and cannot determine a type of declaration. At the same time, * cannot be used on a non-type pointer, because the system does not have the information that this address points to the object size. During the compilation phase, the compiler cannot know the type of the input function parameter. To implement a generic function, you need to input the address space size of the object to be exchanged at the place where the function is called, and use the string in the header file. the memcpy () function defined in h. The changes are as follows:

Void swap (void * VP1, void * VP2, int size) {<br/> char buffer [size];/* Note that the GCC compiler allows such declaration, in my opinion, the VC compiler is not allowed. */<Br/> memcpy (buffer, P0, size); <br/> memcpy, size); <br/>} 

Function memcpy ()

Prototype: void * memcpy (void * dest, void * src, unsigned int n)

Purpose: Copy n Bytes from the memory area indicated by src to the memory area indicated by dest.

Note: the memory areas specified by src and dest cannot overlap. The function returns a pointer to dest.

The buffer is declared as char only because the size of the char type is 1 byte. In this way, the buffer can be allocated with a size byte.

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

Int x = 27, y = 2; <br/> swap (& X, & Y, sizeof (INT )); 

In fact, you will find that there is no error in such a call:

Int I = 44; <br/> short S = 5; <br/> swap (& I, & S, sizeof (short )); 

Two variables of different types can also be exchanged. However, the results displayed vary depending on the system, that is, whether the small-end method or the big-end method stores data. Taking the more common small-end method in Windows or linux as an example, the function swap switches the 16-bit low of integer I and the 16-bit short integer.

This call is feasible. It also reminds us that it is not safe to implement generic programming in C language. The Compiler only performs limited checks, and more requires the attention of programmers.The following calls are acceptable, but meaningless:

 

 

Int I = 22; <br/> short S = 11; <br/> swap (& I, & S, 8 ); 

This function is called to exchange the 8-byte content after the address of exchange I with the content of the last 8 bytes after the address of s, and for the short type s with the size of 2 bytes, A 4-byte int type I operation is meaningless. Pay attention to this when programming. C language provides us with a lot of operations close to the underlying machine, but it is alsoDouble-edged sword.

The following shows the call:

Char * husband = strdup ("Fred"); <br/> char * wife = strdup ("Linda"); <br/> swap (& husband, & wife, sizeof (char *)); 

Function strdup (): Prototype: char * strdup (char * s ). It is used to copy strings.

Husband and wife are two strings. When switching such a type, the address of the two strings cannot be directly transferred to the swap function, because the size of the two strings is not certain, an error will certainly occur when copying. Here, the addresses of the pointers that store the first two strings are exchanged, so that the two pointers direct to the other string to achieve string exchange. It is also possible to write char ** in sizeof (). It is also possible to write double *, because the size of all pointers is 4 bytes. But writing it as char * makes it clearer that reading code by others will cause less misunderstanding, because husband and wife are primary pointers of the char type.

 

The following describes another function:

Int lsearch (INT key, int array [], int size) {<br/> for (INT I = 0; I <size; ++ I) <br/> If (array [I] = Key) <br/> return I; <br/> return-1; <br/>} 

This function searches for the key element in the array and returns its index. If-1 is not found, the returned result is-1. As shown above. You can also implement a generic function:

Void * lsearch (void * Key, void * base, int N, int elemsize) {<br/> for (INT I = 0; I <n; ++ I) {<br/> void * elemaddr = (char *) base + I * elemsize;/* focus, read this line of code carefully */<br/> If (memcmp (key, elemaddr, elemsize) = 0) <br/> return elemaddr; <br/> return NULL; <br/>}< br/>} 

Line 3 of the Code: forcibly convert the first address of the array to a pointer to the char type, which is a one-byte character, point elemAddr to the first address of the I-1 element of this generic array. As we have already said before, you do not know what type of data you pass in at this time. The system cannot determine the length of an element in the array and the number of bytes required to jump down the element, therefore, the forced conversion to a pointer to char, coupled with the parameter passed in the element size information and the product of the cumulative number I, that is, the offset address, you can get the first address of this array I-1 element. In this way, no matter what type of pointer the input parameter points to, you can get a pointer to the correct element to implement generic programming.

Function memcmp (), prototype: int memcmp (void * DEST, const void * SRC, int N ), compare the content in the address space where the two segments have n headers: DEST and SRC.

This function searches for the key element in the array base. if it finds the key element, its address information is returned. If it cannot find the key element, null is returned.

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

Void * lsearch (void * Key, void * base, int N, int elemsize, INT (* cmpfn) (void *, void *, INT )) {<br/> for (INT I = 0; I <n; ++ I) {<br/> void * elemaddr = (char *) base + I * elemsize; <br/> If (cmpfn (Key, elemaddr, elemsize) = 0) <br/> return elemaddr; <br/> return NULL; <br/>}< br/>} 

When calling a function, you can pass in the pointer of a function with the same behavior to implement different lsearch functions.

Function pointer:

Return type (* function pointer name) (parameter table)

 

In summary, the C language can also implement certain generic programming, but this is not safe, and the system only has limited checks on it. Be careful when programming.

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.