generic data structure in C

13.4k views Asked by At

Is there any way to create generic data structure in C and use functions in accordance with the stored data type, a structure that has various types of data and for example can be printed according to the stored data.

For example,

Suppose I wish to make a binary search tree that has just float's, int's stored. The natural approach to do would be to create an enumeration with int's and float's. it would look something like this:

Typedef enum {INT, FLOAT} DataType;

Typedef struct node
{
    void *data;
    DataType t;
    struct node *left,
                *right;
}Node;

if i want print it out:

void printTree(Node *n)
{
    if (n != NULL)
    {
        if (n->t == INT)
        {
            int *a = (int *) n->data;
            printf("%d ", *a);
        }
        else
        {
            float *a = (float *) n->data;
            printf("%f ", *a);
        }

        printTree(n->left);
        printTree(n->right);
    }
}

That's ok but i want to store another data type as a stack, query or something else. So that's why I created a tree that does not depends on a specific data type, such as:

Typedef struct node
{
    void *data;
    struct node *left,
                *right;
}Node;

If i want to print it out i use callback functions, such as:

Node *printTree(Node *n, void (*print)(const void *))
{
    if (n != NULL)
    {
        print(n->data);
        printTree(a->left);
        printTree(a->right);
    }
}

But it falls down when i try to insert a integer and a float and print it out. My question is, Is there a way of creating a generic data structure that a routine depends on a specific data type in one situation but another situation it doesn't , for mixed data type? In this situation i should create a structure that stores int's and float's stores it and use a print function like in the first print code for that in the callback function?

observation: I just declared a node in the structure and did everything on it trying to simplify, but the idea is to use the structure with .h and .c and all this abstraction involving data structures.

3

There are 3 answers

1
JDS On BEST ANSWER

C doesn't support this kind of generic data types/structures. You have a few options you can go with:

  • If you have the opportunity to use Clang as the compiler, there's a language extension to overload functions in C. But you have to cast the argument to the specific type, so the compiler knows which function to call.

  • Use C++

    • although you still have to cast the argument, so the compiler knows which of the available functions called print he has to call.

    • use templates

  • Create a function called print which takes something like

    struct data_info {
      void *data;
      enum_describing_type type;
    }
    

    print does a switch and calls the appropriate printInt, printFloat etc.

3
AudioBubble On

I would suggest trying something like the following. You'll noticed that Node contains a tagged union that allows for either a pointer type, an integer, or a floating point number. When Node is a pointer type, the custom print function is called, and in the other cases, the appropriate printf format is used.

typedef enum {POINTER, INT, FLOAT} DataType;

typedef struct node
{
    DataType t;
    union {
        void *pointer;
        int integer;
        float floating;
    } data;
    struct node *left,
                *right;
} Node;

void printTree(Node *n, void (*print)(const void *))
{
    if (n != NULL) {
        switch (n->t) {
            case POINTER:
                print(n->data.pointer);
                break;
            case INT:
                printf("%d ", n->data.integer);
                break;
            case FLOAT:
                printf("%f ", n->data.floating);
                break;
        }
        printTree(a->left, print);
        printTree(a->right, print);
    }
}
0
Jonathon Reinhart On

uthash is a collection of header files that provide typed hash table, linked list, etc. implementations, all using C preprocessor macros.