Is it possible to dynamically define a struct in C

前端 未结 6 1999
暗喜
暗喜 2020-12-14 16:16

I\'m pretty sure this will end up being a really obvious question, and that\'s why I haven\'t found much information on it. Still, I thought it was worth asking :)

B

6条回答
  •  情书的邮戳
    2020-12-14 17:00

    Based on gerty3000's answer I made a library. I've abstracted something from the final user. It was hard buf finaly worked. If is there any improvement to do I am open for sugestions. Here it goes the code.

    type-machine.h // define types and function prototipes

    #ifndef TYPE_MACHINE_H
    #define TYPE_MACHINE_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #define B8 char
    #define B8U unsigned char
    #define B16 short
    #define B16U unsigned short
    #define B32 int
    #define B32U unsigned int
    #define B64 long long int
    #define B64U unsigned long long int
    #define BP32 float
    #define BP64 double
    
    #define BIT_ON(var,bit)   ((var)=((var) | (bit)))
    #define BIT_OFF(var,bit) ((var)=((var) & (~bit)))
    #define BIT_IS_ON(var,bit) (var & bit)
    #define PAIR(position,value) ((value)=((position) << (1)))
    
        typedef struct Bit8Tag BIT;
    
        typedef enum {
            Off, On
        } STATUS;
    
        typedef enum {
            B8_T, B8U_T, B16_T, B16U_T, B32_T, B64_T, B64U_T, B32U_T, BP32_T, BP64_T
        } TYPE;
    
        typedef struct ClassFieldTag ClassField;
        typedef struct ClassTag Class;
    
        typedef enum {
            CLASS_SIZE, CLASS_INSERT, CLASS_SHOW
        } CLASS_MODE;
    
    #if (defined(WIN32) || defined(WINDOWS_XP))
    
    #define is_win()(1)
    
    #else
    
    #define is_win()(0)
    
    #define TYPE_CALL
    #define TYPE_TYPE
    
    #endif // WIN32
    
    #include 
    #include 
    #include 
    
    #define area(a,b) ((a)*(b))
    #define radian(x,y)(atan2(y,x))
    #define angle(a)( (a * (180 / M_PI)) + 180)
    
    #if defined WIN32
    #define ARIAL_PATH "C:/Windows/Fonts/arial.ttf\0"
    #else
    #define ARIAL_PATH "home/media/TheGreat/\0"
    #endif
    
        struct ClassFieldTag {
            TYPE type;
            size_t mem, size, len;
            B8 name[32];
            struct ClassFieldTag * next, *preview;
        };
    
        extern ClassField * class_set_push();
        extern ClassField * class_field_set(ClassField * set, TYPE type, B8 * name, size_t len, size_t mem);
        extern STATUS class_set_next_back(ClassField ** set, ClassField * next);
        extern STATUS class_set_next_front(ClassField ** set, ClassField * next);
        extern STATUS class_insert_back(Class * set, TYPE type, B8 * name, size_t len);
        extern STATUS class_insert_front(Class * set, TYPE type, B8 * name, size_t len);
    
        struct ClassTag {
            B8 name[32];
            void * data;
            B8 * String;
            B16 Short;
            B16U UShort;
            B32 Int;
            B32U UInt;
            B64 Long;
            B64 ULong;
            BP32 Float;
            BP64 Double;
            ClassField * field;
        };
    
        Class * class_push(B8 name[32]);
        extern STATUS class_zero(Class * set, B8 name[32]);
        extern void class_data_push(Class * set);
        extern void class_data_pop(Class * set);
        extern void * class_set_to(Class * set, ClassField * field);
        extern void class_int_set(Class * set, ClassField * field, B32 value);
        extern B32 class_int_get(Class * set, ClassField * field);
        extern void class_double_set(Class * set, ClassField * field, BP64 value);
        extern BP64 class_double_get(Class * set, ClassField * field);
        extern void class_string_set(Class * set, ClassField * field, B8 * value);
        extern B8 * class_string_get(Class * set, ClassField * field);
        extern void class_mode(Class * set, ClassField * field, CLASS_MODE mode);
        extern void class_field_pop(Class * set);
        extern void class_pop(Class * set);
    
        extern STATUS class_ex(Class * mine);
    
        struct Bit8Tag {
            unsigned b16 : 16;
        };
    
        extern void bit_on(BIT * value, int bit);
        extern void bit_off(BIT * value, int bit);
        extern STATUS bit_is_on(BIT value, int bit);
        extern B32U strsub(B8 * data, B8 * key);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif // TYPE_MACHINE_H
    

    type-machine.c // declares those functions

    #include 
    #include 
    #include 
    
    Class * class_push(B8 name[32]) {
        Class * set = (Class *) malloc(sizeof (Class));
        if(class_zero(set,name)){
            return(set);
        }
        return(NULL);
    }
    
    void class_data_push(Class * set) {
        B32 class_size = sizeof (Class), class_field_size = sizeof (ClassField);
        if (set) {
            if (class_size < sizeof (set))class_size = sizeof (set);
            if (class_field_size < sizeof (set->field))class_field_size = sizeof (set->field);
        }
        set->data = malloc(class_size + class_field_size + 1);
    }
    
    void class_data_pop(Class * set) {
        if (set && set->data) {
            free(set->data);
        }
    }
    
    void * class_set_to(Class * set, ClassField * field) {
        if (set && set->data && field) {
            void * data = (char *) set->data + field->mem;
            return data;
        }
        return (NULL);
    }
    
    void class_int_set(Class * set, ClassField * field, B32 value) {
        if (set) {
            assert(field->type == B32_T);
            B32 * update = class_set_to(set, field);
            *update = value;
        }
    }
    
    B32 class_int_get(Class * set, ClassField * field) {
        if (set) {
            assert(field->type == B32_T);
            B32 * data = class_set_to(set, field);
            return (*data);
        }
        return (0);
    }
    
    void class_double_set(Class * set, ClassField * field, BP64 value) {
        if (set) {
            assert(field->type == BP64_T);
            BP64 * update = class_set_to(set, field);
            *update = value;
        }
    }
    
    BP64 class_double_get(Class * set, ClassField * field) {
        if (set) {
            assert(field->type == BP64_T);
            BP64 * data = class_set_to(set, field);
            return (*data);
        }
        return (0);
    }
    
    void class_string_set(Class * set, ClassField * field, B8 * value) {
        if (set && field && field->len > 1 && value) {
            assert(field->type == B8_T);
            size_t len = strlen(value);
            if (len < 2) {
                len = 2;
            }
            if (len > field->len)len = field->len - 1;
            B8 * buffer = class_set_to(set, field);
            if (buffer) {
                memmove(buffer, value, len);
                buffer[len] = '\0';
            }
        }
    }
    
    B8 * class_string_get(Class * set, ClassField * field) {
        if (set && field) {
            assert(field->type == B8_T);
            B8 * data = class_set_to(set, field);
            return (data);
        }
        return (NULL);
    }
    
    STATUS class_zero(Class * set, B8 * name) {
        if (set) {
            set->String = NULL;
            set->Short = 0;
            set->UShort = 0;
            set->Int = 0;
            set->UInt = 0;
            set->Long = 0;
            set->ULong = 0;
            set->Float = 0;
            set->Double = 0;
            set->data = NULL;
            memset(set->name, 0, sizeof (set->name));
            if (name)memmove(set->name, name, strlen(name));
            set->field = NULL;
            return (On);
        }
        return (Off);
    }
    
    ClassField * class_set_push() {
        return (malloc(sizeof (ClassField)));
    }
    
    void class_field_pop(Class * set) {
        if (set) {
            ClassField * field = set->field;
            while (field) {
                ClassField * next = field->next;
                if (field) {
                    free(field);
                    field = NULL;
                }
                field = next;
            }
        }
    }
    
    void class_pop(Class * set) {
        if (set) {
            class_data_pop(set);
            class_field_pop(set);
            free(set);
            set = NULL;
        }
    }
    
    ClassField * class_field_set(ClassField * field, TYPE type, B8 * name, size_t len, size_t mem) {
        if (field) {
            size_t lenght = (name) ? strlen(name) : 0;
            if (lenght > 32) {
                lenght = 31;
            }
            memcpy(field->name, name, lenght);
            field->name[lenght] = 0;
            field->type = type;
            field->mem = mem;
            field->len = len;
            class_mode(NULL, field, CLASS_SIZE);
            field->next = NULL;
            field->preview = NULL;
            return (field);
        }
        return (NULL);
    }
    
    STATUS class_set_next_back(ClassField ** field, ClassField * next) {
        if (next == NULL)return (Off);
        next->next = *field;
        if (*field != NULL) {
            (*field)->preview = next;
        }
        *field = next;
        return (On);
    }
    
    STATUS class_set_next_front(ClassField ** field, ClassField * next) {
        if (next == NULL)return (Off);
        if (*field != NULL) {
            ClassField * update = *field, *preview = NULL;
            while (update->next != NULL) {
                preview = update;
                update = update->next;
            }
            update->preview = preview;
            update->next = next;
            return (On);
        }
        *field = next;
        return (On);
    }
    
    STATUS class_insert_back(Class * set, TYPE type, B8 * name, size_t len) {
        if (class_set_next_back(&set->field, class_field_set(class_set_push(), type, name, len, 0))) {
            ClassField * preview = set->field;
            if (preview->next) {
                preview->mem = preview->next->mem + preview->next->size;
            }
            return (On);
        }
        return (Off);
    }
    
    STATUS class_insert_front(Class * set, TYPE type, B8 * name, size_t len) {
        ClassField * next = class_field_set(class_set_push(), type, name, len, 0);
        if (class_set_next_front(&set->field, next)) {
            ClassField * preview = set->field;
            while (preview) {
                if (preview->next) {
                    if (preview->next == next) {
                        next->mem = preview->mem + preview->size;
                    }
                }
                preview = preview->next;
            }
            return (On);
        }
        return (Off);
    }
    
    void class_mode(Class * set, ClassField * field, CLASS_MODE mode) {
        if (field) {
            switch (field->type) {
                case B8_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: %s\n", field->name, class_string_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = field->len * sizeof (B8);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_string_set(set, field, set->String);
                        }
                            break;
                    }
                }
                    break;
                case B8U_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: %s\n", field->name, class_string_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = field->len * sizeof (B8U);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_string_set(set, field, set->String);
                        }
                            break;
                    }
                }
                    break;
                case B16_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%i]\n", field->name, class_int_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (B16);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_int_set(set, field, set->Int);
                        }
                            break;
                    }
                }
                    break;
                case B16U_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%i]\n", field->name, class_int_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (B16U);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_int_set(set, field, set->Int);
                        }
                            break;
                    }
                }
                    break;
                case B32_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: %i\n", field->name, class_int_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (B32);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_int_set(set, field, set->Int);
                        }
                            break;
                    }
                }
                    break;
                case B32U_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%i]\n", field->name, class_int_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (B32U);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_int_set(set, field, set->Int);
                        }
                            break;
                    }
                }
                    break;
                case B64_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%i]\n", field->name, class_int_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (B64);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_int_set(set, field, set->Int);
                        }
                            break;
                    }
                }
                    break;
                case B64U_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%i]\n", field->name, class_int_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (B64U);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_int_set(set, field, set->Int);
                        }
                            break;
                    }
                }
                    break;
                case BP32_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%lf]\n", field->name, class_double_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (BP32);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_double_set(set, field, set->Double);
                        }
                            break;
                    }
                }
                    break;
                case BP64_T:
                {
                    switch (mode) {
                        case CLASS_SHOW:
                        {
                            printf("%s: [%lf]\n", field->name, class_double_get(set, field));
                        }
                            break;
                        case CLASS_SIZE:
                        {
                            field->size = sizeof (BP64);
                        }
                            break;
                        case CLASS_INSERT:
                        {
                            class_double_set(set, field, set->Double);
                        }
                            break;
                    }
                }
                    break;
            }
        }
    }
    
    void bit_on(BIT * value, int bit) {
        BIT_ON(value->b16, bit);
    }
    
    void bit_off(BIT * value, int bit) {
        BIT_OFF(value->b16, bit);
    }
    
    STATUS bit_is_on(BIT value, int bit) {
        if (value.b16 & bit)return (On);
        return (Off);
    }
    
    B32U strsub(B8 * data, B8 * key) {
        if (data && key) {
            B8 *d = data;
            B32U len = strlen(key), p = 0;
            if (len > strlen(d))return (0);
            while (*d != '\0') {
                if (*(d + len) != '\0') {
                    B32U x = 0;
                    while (x <= len) {
                        if (key[x] == *d) {
                            *d++;
                            p++;
                        } else break;
                        x++;
                    }
                    if (x == len)return (p);
                } else if (len == 1) {
                    if (*d == key[0])return (p);
                }
                p++;
                *d++;
            }
        }
        return (0);
    }
    

    main.c // testing....

    #include "network.h"
    #include 
    
    STATUS class_ex(Class * set) {
        class_data_push(set);
        if (set->data) {
            ClassField * field = set->field;
            while (field) {
                if (!strcmp(field->name, "peso")) {
                    set->Double = 65.5;
                }
                if (!strcmp(field->name, "idade")) {
                    set->Int = 29;
                }
                if (!strcmp(field->name, "nome")) {
                    set->String = "Lisias de Castro Martins";
                }
                if (!strcmp(field->name, "endereco")) {
                    set->String = "Rua Mae D'Agua";
                }
                class_mode(set, field, CLASS_INSERT);
                class_mode(set, field, CLASS_SHOW);
                field = field->next;
            }
            return (On);
        }
        return (Off);
    }
    
    int main(int argc, char** argv) {
        STATUS client_start = On;
        if (client_start) {
            Class * client = class_push("Client");;
            class_insert_back(client, BP64_T, "peso", 1);
            class_insert_back(client, B8_T, "endereco", 32);
            class_insert_back(client, B32_T, "idade", 1);
            class_insert_back(client, B8_T, "nome", 64);
            printf("Classe[%s]\n\n", client->name);
            if (class_ex(client)) {
            }
            class_pop(client);
            getch();
        }
        return (EXIT_SUCCESS);
    }
    

    I still have to implement the short double and some other functions, but it is working.

提交回复
热议问题