Are there patterns in the C programming language?

I am writing a linked list implementation in C and would like to use a language function equivalent to C ++ templates to facilitate my work.

Is there such a function?

+7
source share
5 answers

C does not have templates like C ++, although you can achieve something similar with smart (or WTFey, depending on how you look at it) using #define macros.

However, see how, for example, GLib does this for single lists or doubly linked lists .

+6
source

Templates are C ++ functions, but if you need a type-independent implementation of a single or doubly linked list, you can do it with macros or just save void* pointers in your structure.

Of course, there are many such implementations on the Internet. @MohamedKALLEL and @hyde have already given examples from the Linux kernel and from GLib, I would just like to add a note about the small little uthash library.

It implements a hash table in C, but also has utlist.h , which implements single and doubly connected (and even circular) lists completely on macros. That is, you can simply take this file, include it, and either use these macros as is, or modify it for your needs. It’s also nice that you can use any of your data structures: for this you need to have a next pointer (and prev if it has a double binding).

Ps But always remember when using macros: with great power brings great responsibility . Macros are powerful, but can become extremely dangerous and unreadable. Caution!

+4
source

Yes, there is list.h. And this is a circular linked list:

The following link contains an example of how to use it.

list.h contains all the functions related to managing a circular linked list, such as definition, append to the head, append to the tail, delete, foreach function to view the circular linked list ...

+3
source

Hi, I don't know about linked lists, but for a template function, u can probably use a macro or function with a different number of arguments as an example of this program

 #include <stdarg.h> #include <stdio.h> #define INT 0 #define STR 1 void foo( int type, ... ) { va_list ap; int i; char *s; va_start( ap, type ); switch( type ) { case INT: i = va_arg( ap, int ); printf( "INT: %i\n", i ); break; case STR: s = va_arg( ap, char * ); printf( "STR: %s\n", s ); break; default: break; } va_end( ap ); } #define SWAP( type, a, b ) { \ type t; \ t = a; \ a = b; \ b = t; \ } int main( void ) { foo( INT, 3 ); foo( STR, "baz" ); int ia = 0, ib = 3; SWAP( int, ia, ib ); printf( "%i %i\n", ia, ib ); float fa = 0.5, fb = 3.14; SWAP( float, fa, fb ); printf( "%f %f\n", fa, fb ); return 0; } 

will produce output

 INT: 3 STR: baz 3 0 3.140000 0.500000 
+1
source

If you use make to build your software, one approach you can use to achieve a similar result is to let make generate your code based on the template you wrote, invoking something like sed or awk. I have used this approach many times, and although it lacks the flexibility and capabilities that C ++ templates offer, it is extremely transparent (unlike macros), it is very efficiently built and does not require any additional tools, except for the proven old school Unix utility (for example, make and sed ). The main disadvantage is that you will specify the search / replace lines in a different place (the line in the Makefile) than your code.

Note that often you are better off using function pointers and void pointers to just write one universal code base. However, if you want additional performance to eliminate unnecessary function calls, for example, in tight cycles, templates can be better and can be emulated as follows:

  1. Write the template code using placeholder names with the name of the template, for example code.template.c

  2. Write your non-template code using function calls for your template code, after replacing in the appropriate names, for example, my_int_func() or my_string_func()

  3. Perhaps use #include to include the template code in code that is not associated with the template (for example, if your template will have inline functions)

  4. Write your Makefile at:

    • Create the β€œreal” C files from the template.c file. You will have one Makefile entry for each template target, for example code.generated.c. sed is a good replacement tool, but you can also use, for example, replace or awk or any of their equivalents on Windows
    • If necessary, compile the generated C files and link the generated objects

For instance:

code.template.c

 /* Makefile will call sed to replace DATANAME, DATATYPE and SPECIFIER */ void print_DATANAME_data(DATATYPE x) { printf("%SPECIFIER\n", x); } 

code.c

 #include <stdio.h> #include "printfuncs.generated.c" int main() { int i = 99; print_int_data(99); char *s = "hello"; print_str_data(s); float f = 1.234; print_float_data(f); } 

Makefile

 all: my_program my_program: code.c CC -o $@ code.c code.c: printfuncs.generated.c printfuncs.generated.c: code.template.c rm -f printfuncs.generated.c cat code.template.c | sed 's/DATANAME/int/g;s/DATATYPE/int/g;s/SPECIFIER/i/g;' >> printfuncs.generated.c cat code.template.c | sed 's/DATANAME/str/g;s/DATATYPE/char */g;s/SPECIFIER/s/g;' >> printfuncs.generated.c cat code.template.c | sed 's/DATANAME/float/g;s/DATATYPE/float/g;s/SPECIFIER/f/g;' >> printfuncs.generated.c 

build

 make 

This will create a file printfuncs.generated.c (if this file does not exist or changed not so long ago as code.template.c), which will look like this:

 /* Makefile will call sed to replace int, int and i */ void print_int_data(int x) { printf("%i", x); } /* Makefile will call sed to replace str, char * and s */ void print_str_data(char * x) { printf("%s", x); } /* Makefile will call sed to replace float, float and f */ void print_float_data(float x) { printf("%f", x); } 

Any compiler errors will point to this file, and you can either tinker with this file directly to compile it (after which you will need to update the template to prevent loss of changes), or edit the template. In any case, after your changes, what you need to do is run make to (try) compile again.

run

./my_program (or my_program.exe , if built on victory)

+1
source

All Articles