8

Hii ,

While I was implementing some of the programs for the class assignment, it just struck me how it would be to implement the same in a generic fashion using C.

I do know that we need to make use of the void pointers and functions but i was just stuck as to how to do it. Please give me an example that is simple and demonstrates the usage .

Like how to implement a comparison function to implement a comparison sort , or to insert into a linked list where each node has a element of varied type etc...

P.S : Any links to other questions or articles are helpful and welcome.

Flash
  • 2,901
  • 5
  • 38
  • 55
  • Do you mean "generics"? http://download.oracle.com/javase/tutorial/extra/generics/index.html – Prof. Falken Nov 20 '10 at 12:04
  • 2
    You upgrade to C++ and use templates, that's how. – Puppy Nov 20 '10 at 12:12
  • 2
    @deadMG : i know to program the same using generics in C++. I wanted to know how to do it in C . – Flash Nov 20 '10 at 12:17
  • 3
    Take a look at the standard implementation of `qsort` – ruslik Nov 20 '10 at 12:38
  • `generic` is a concept of OOP. Fortunately C is not OOP. Probably you mean casting of pointers. – khachik Nov 20 '10 at 12:38
  • @khachik - Generics are not specific to OO, I've never seen a functional language that doesn't support them. – Lee Nov 20 '10 at 13:00
  • @Lee could you please point where are generics in Common Lisp, without considering CLOS? – khachik Nov 20 '10 at 13:04
  • @khachik - Ok, I can't think of a statically-typed functional language that doesn't support it. – Lee Nov 20 '10 at 13:14
  • @Lee Which one? Just interesting, thanks in advance – khachik Nov 20 '10 at 13:16
  • @khachik - ML dialects (e.g. SML, F#, OCaml) and Haskell all support it. I can't imagine (static) functional programming could work well without it. – Lee Nov 20 '10 at 13:31
  • @khachik Why do you think that only object-oriented languages may support generic programming? –  Nov 20 '10 at 13:38
  • @Lee probably every language that has some equivalent of eval() might be considered to support generic programming. –  Nov 20 '10 at 13:42
  • @Gregory Maybe because I've come to generics using CLOS... There are many opinions what is "generic programming" and where it originates from... This article is interesting http://lcsd05.cs.tamu.edu/papers/dos_reis_et_al.pdf. I don't think that only OO languages may support generic programming. I think that it is best reflected to OO languages (@Lee BTW, F#, OCaml are oo as well, Standard ML is not...) and originates from Ada (but I just found there are another opinions). Well, maybe I'm wrong. – khachik Nov 20 '10 at 16:20

3 Answers3

3

Well, obviously one way to parametrize types is to use the preprocessor, e.g.:

#define DIVIDE_FUNC(type) divide_##type
#define DIVIDE_CALL(type, a, b) DIVIDE_FUNC(type)((a), (b))
#define DIVIDE_DECL(type) type DIVIDE_FUNC(type)(type a, type b)
#define DIVIDE_IMPLEMENTATION DIVIDE_DECL(DIVIDE_TYPE) { return a / b; }

#define DIVIDE_TYPE int
DIVIDE_IMPLEMENTATION
#undef DIVIDE_TYPE
#define DIVIDE_TYPE double
DIVIDE_IMPLEMENTATION

#include <stdio.h>

int main (void) {
    int i = 5, j = 2;
    (void) printf("int %d / %d = %d\n", i, j, DIVIDE_CALL(int, i, j));
    (void) printf("double %d / %d = %f\n", i, j, DIVIDE_CALL(double, i, j));
    return 0;
}

This implements two functions: divide_double and divide_int. In a more complex (realistic) example the implementation could be in a separate compilation file which is compiled (or included) separately for each type with a different DIVIDE_TYPE defined.

The downside compared to real generics is that the implementations for different types are not automatically generated, i.e. DIVIDE_CALL(mytype, x, y) does not cause the implementation for mytype to be generated. (Of course this could be arranged with some relatively simple scripting, but then one might argue that you are not really using C anymore and there are languages with prettier built-in generics. =)

In any case, this can work for data structures and such where the actual data type (not a void * pointer) is desired.

Arkku
  • 41,011
  • 10
  • 62
  • 84
  • 2
    Stroustrup's first C++ book didn't have templates. There was an example of how to define generic list using macros, it was similar to your code. – liori Nov 20 '10 at 13:13
2

You can use void* pointers, then a lot of casting. Note that you'll need to store the type somehow to recast back to the original element, so it's not exactly generic, but about as close as you'll get.

Obviously this sort of code is very error-prone

rtpg
  • 2,419
  • 1
  • 18
  • 31
0

Something like this: https://github.com/10098/breakout/tree/master/dl_list/

It's an implementation of a doubly linked list that I wrote as an exercise. I use it in a simple breakout-like game.

  • but how do you get the data type for each node ? – Yanick Rochon Nov 20 '10 at 13:33
  • I don't. All the routines that perform operations on the linked list are type agnostic. If someone needs something type-specific, this can be done through callback functions that would cast void pointers to necessary types and do the required operations. I'm not saying it's the best approach of course. Maybe somebody will point me to a better implementation. –  Nov 20 '10 at 13:35