Common Initial Sequence

From C

Jump to: navigation, search

If you have multiple structs that share a common initial sequence, you can generalize the access to this sequence by either containing the sequence within a sub-struct, or by using a union to contain the structs.

Code sample #1

The following code sample uses a struct to contain the common initial sequence, it's required to position this struct as the first member.

#include <stdio.h>

struct common {
    int flag;
    int active;
};

struct s1 {
    struct common common;
    long int ld;
};

struct s2 {
    struct common common;
    int d;
    char c;
};

struct s3 {
    struct common common;
    int x;
};

void func(void *p) {
    struct common *common = p;
    
    if (common->active != 1) {
        puts("Inactive.");
        return;
    }
    
    switch (common->flag) {
        case 1: {
            struct s1 *s1 = p;
            printf("s1->u: %ld\n", s1->ld);
            break;
        }
        case 2: {
            struct s2 *s2 = p;
            printf("s2->d: %d\n", s2->d);
            printf("s2->c: %d\n", s2->c);
            break;
        }
        case 3: {
            struct s3 *s3 = p;
            printf("s3->x: %d\n", s3->x);
            break;
        }
        default: {
            printf("Unknown flag: %d\n", common->flag);
        }
        
    }
}

int main(void) {
    struct s1 s1 = {
        { .flag = 1, .active = 1 },
        123123123
    };
    struct s2 s2 = {
        { .flag = 2, .active = 1 },
        123,
        'A'
    };
    struct s3 s3 = {
        { .flag = 3, .active = 0 },
        999
    };
    
    puts("func(&s1)");
    func(&s1);
    puts("");

    puts("func(&s2)");
    func(&s2);
    puts("");

    puts("func(&s3)");
    func(&s3);
    puts("");
    
    return 0;
}

Code sample #2

The following code sample uses a union to contain all the structs that share a common initial sequence, it's required to access the members through the union.

#include <stdio.h>

struct common_s {
    int flag;
    int active;
};

struct s1 {
    int flag;
    int active;
    
    long int ld;
};

struct s2 {
    int flag;
    int active;
    
    int d;
    char c;
};

struct s3 {
    int flag;
    int active;
    
    int x;
};

union common {
    struct common_s common;
    struct s1 s1;
    struct s2 s2;
    struct s3 s3;
};

void func(union common *p) {
    if (p->common.active != 1) {
        puts("Inactive.");
        return;
    }
    
    switch (p->common.flag) {
        case 1: {
            printf("s1->u: %ld\n", p->s1.ld);
            break;
        }
        case 2: {
            printf("s2->d: %d\n", p->s2.d);
            printf("s2->c: %c\n", p->s2.c);
            break;
        }
        case 3: {
            printf("s3->x: %d\n", p->s3.x);
            break;
        }
        default: {
            printf("Unknown flag: %d\n", p->common.flag);
        }
    }
}

int main(void) {
    union common u1 = {
        .s1 = {
            .flag = 1,
            .active = 1,
            123123123
        }
    };
    union common u2 = {
        .s2 = {
            .flag = 2,
            .active = 1,
            123,
            'A'
        }
    };
    union common u3 = {
        .s3 = {
            .flag = 3,
            .active = 0,
            999
        }
    };
    
    puts("func(&u1)");
    func(&u1);
    puts("");
    
    puts("func(&u2)");
    func(&u2);
    puts("");
    
    puts("func(&u3)");
    func(&u3);
    puts("");
    
    return 0;
}

.

Personal tools