Question

Assume we have two different struct that have mostly common fields but one or two different fields or less fields. For example:

typedef struct HobbyNodetag {
    char *name; // hobby name
    struct HobbyNodetag* link; // link to next HobbyNode
    int count; // number of times this hobby was mentioned by user
    // more fields... 
    // but identical type/variable name with MyHobbyList
} HobbyNode; // database of entire hobby node; singly linked list

typedef struct MyHobbyTag{
    char *name; // hobby name
    struct MyHobbyTag* link; // linked to next MyHobbyNode
    // more fields... 
    // but identical type/variable name with EntireHobbyList
} MyHobbyNode; // single person's hobby node; singly linked list

Do we have more efficient/elegant coding practice to use above two structs? Wouldn't this be a waste of having two different structs as they share majority of the fields?

UPDATE

My earlier question was misleading. The above example is the node and singly linked (by link).

Was it helpful?

Solution

You can move all the extra fields (which are present in the second struct but not in the first one) to the end of the struct type definition, then use the smaller struct as the "base" of the bigger one:

struct BaseFoo {
    int count;
    char name[128];
    float value;
};

struct ExtendedFoo {
    struct BaseFoo base;
    struct ExtendedFoo *next;
};

What is nice about this solution is that you can have "polymorphism": since the C standard guarantees that there is no padding before the first struct member in memory, this will work just fine:

void print_name(struct BaseFoo *foo)
{
    printf("Count: %d\n", foo->count);
    printf("Name: %s\n", foo->name);
}

struct ExtendedFoo foo = { /* initialize it */ };
print_name((BaseFoo *)&foo);

OTHER TIPS

You can do something like this, but I believe that's not what you're after.

typedef struct myHobbyTag{
    char *name;
    struct myHobbyTag* link; 

} MyHobbyList; 

typedef struct entireHobbytag {
    MyHobbyList commonPart;

    int count;
} EntireHobbyList; 

If you move all of the common fields to the top, you can declare a base class and an inheriting class using OOP in C (search for it on StackOverflow.)

There are basically two ways to do this.

  1. You declare a base class, then in the inheriting class (which has more fields) you put the base class as a member at the top of the inheriting class.

    struct hobbyLink; // common link

    typedef struct baseHobbytag {
        char *name;
        struct hobbyLink* link;
    } BaseHobby; 
    
    typedef struct myHobbyTag{
        BaseHobby  hobby;
        int count;
        // more fields...
    } HobbyTag;
    
  2. You use a #define for all of the common base members, and put that #define in all inheriting classes.

    #define BASEHOBBY_MEMBERS   \
    char *name;             \
    struct hobbyLink* link;
    
    // base class
    typedef struct baseHobbytag {
        BASEHOBBY_MEMBERS   
    } BaseHobby;
    
    // Inherit basehobby    
    typedef struct myHobbyTag{
        BASEHOBBY_MEMBERS   
        int count;
        // more fields...
    } HobbyTag;
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top