Click here to Skip to main content
15,885,720 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Back in the days when C was widely used than C++, how was the data structures handled ? I mean when creating data structures in C++, we usually get the use of templates, which is a huge advantage for the programmer. With C++ you can implement a linked list (or some other data structure) once and use it all the time with different data types as want.

With my understanding, in C or any other language which do not support template meta-programming you have to rewrite all the code in a particular data structure when you want to change it's node type.

i.e; A linked list of type int is written in C. If you want the same linked list to work with doubles, how do you do that ?

Unix, Windows (a very large portion), My SQL....[etc] is written in C. They must contain dozens of data structures. Did those programmers who wrote those software, rewrote all the similar data structures that work with different data types ? Or Was any other method used ?
Posted
Updated 25-Sep-13 4:44am
v2

1 solution

There are many ways to implement for example containers. None of them are so clean as using templates/generics.

1. One trick is using void pointers in the container implementation and later you store pointers to the items you want to store in the container. Of course you have to do ugly casts with this implementation and you are using pointers unnecessary compared to C++ templates where you can store the items by value without allocations. If you want to store primitive types like char and short you can cast these into pointers and store them directly by value to the container but your are still wasting space this way if the size of the void* is larger than the primitive you want to store.

2. Many things that you are doing with templates in C++ were done with macros in C. I've seen for example dynamic array implementation where you could generate the source code of the dynamic array for a give type by declaring it with a macro:
C++
// The header file:
typedef struct SMyData
{
    int data0;
    char data1;
    float data2;
} SMyData;


DECLARE_DYN_ARRAY_FUNCTIONS(SMyData)

// the c file:
DEFINE_DYN_ARRAY_FUNCTIONS(SMyData)


// The above macros declared/defined functions like:
void DynArray_SMyData_Add_(DynArray_SMyData* arr, const SMyData* item);
void DynArray_SMyData_Remove(DynArray_SMyData* arr, const SMyData* item);
...

Drawbacks: Lots of code in macros is not only ugly bug undebuggable - you can not place breakpoints in macros.

3.
Another nice trick I've seen in C in a linked list implementation:
C++
typedef struct LinkedListNode
{
    struct LinkedListNode* next;
} LinkedListNode;

void LinkedList_Append(LinkedListNode** head, LinkedListNode* node);
void LinkedList_Remove(LinkedListNode** head, LinkedListNode* node);

#define NODE_TO_DATA(node_ptr, node_member_name, data_type) \
    (data_type*)((char*)node_ptr - offsetof(data_type, node_member_name))

struct SMyNode
{
    int mydata;
    char mydata2;
    float mydata3;
    LinkedListNode node;
};

LinkedListNode* g_Head = NULL;

void LinkedListTest()
{
    // building the list
    LinkedListNode* it;
    SMyNode node0, node1;
    // TODO: fill in nodes with data
    LinkedList_Append(&g_Head, &node0.node);
    LinkedList_Append(&g_Head, &node1.node);

    // iteration, contains a bit of typecast but it isn't that
    it = g_Head;
    while (it)
    {
        SMyNode* node = NODE_TO_DATA(it, node, SMyNode);
        // TODO: use node
        it = it->next;
    }
}

This trick works with any data structures that consist of nodes/items (for example in case of trees) that don't have to be allocated by packing them together like in case of an array. Basically your data contains the container related stuff and not the container contains your data...
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900