【问题标题】:Is it possible to dynamically define a struct in C是否可以在 C 中动态定义结构
【发布时间】:2011-09-05 11:38:59
【问题描述】:

我很确定这最终会成为一个非常明显的问题,这就是为什么我没有找到太多关于它的信息。不过,我认为值得一问:)

基本上,使用结构访问数据非常快。如果数据以一种可以立即作为结构处理的形式从网络中流出,那么从性能的角度来看,这是非常好的。

但是,是否可以动态定义结构。客户端和服务器应用程序能否协商数据流的格式,然后将该定义用作结构?

如果没有,有没有更好的方法?

谢谢大家!

【问题讨论】:

  • 我不是 C 专家,但你不能用你可能需要的一切创建一个结构,然后只填充你想要使用的字段,并为未使用的字段分配一些虚假值?
  • 请注意,当您的两个处理器架构不匹配时,以这种方式发送/接收数据会导致大量艰苦的工作,像成员对齐这样的小事情确实会妨碍 - 除此之外,玩得开心;)
  • @KevinDTimm 好评论哈哈。是的,我知道可能存在潜在问题,但幸运的是,至少在这种情况下,我控制了所有机器及其架构;)

标签: c dynamic struct


【解决方案1】:

不可能动态定义与编译时结构相同的结构。

创建可以包含与结构等效的信息的动态结构是可能的,但很困难。访问数据不如编译时可用的方便。

除此之外,如果成员 somestruct.not_seen_at_compile_time 未在编译时定义,则您无法使用点 . 或箭头 -> 表示法访问该成员。

对于网络通信,还有其他问题需要解决 - 特别是“字节顺序”。也就是说,线路上的数据可能包括多字节(2、4、8)整数,并且首先发送 MSB 或 LSB,但如果一台机器是 little-endian(IA-32、IA- 64,x86/64),另一个是大端(SPARC,PPC,几乎所有不是来自英特尔的),那么数据将需要转换。浮点格式也可能有问题。有许多标准专门用于定义如何通过网络发送数据——这不是微不足道的。有些是特定的:IP、TCP、UDP;其他是通用的,例如 ASN.1。

但是,“不能做动态数据结构”部分限制了一些事情 - 您必须事先就数据结构是什么以及如何解释它们达成一致。


你是怎么做到的?

gerty3000 问:

创建可以包含与结构等效的信息的动态结构是可能的,但很困难。 — 你是如何做到的?我想将动态定义的结构传递给其他 C 代码(假设相同的编译器和其他设置),而不必从编译器复制结构内存布局例程。我不会在我的进程中访问这些结构的字段(只需初始化一次),所以方便的语法不是问题。

如果不以某种形状或形式复制内存布局,您将无法做到这一点。它可能不必完全相同,但如果是,它可能是最好的。下面是一些示例代码,大致展示了它是如何完成的。

dynstruct.c

这包含基本的结构操作材料——用于描述结构和(简单)成员的结构。处理完整的数组(相对于字符串)需要更多的工作,并且需要为其他类型管理大量的临时复制。

它还包含一个测试代码的main() 程序。它调用other_function(),这表明我在数据结构中定义的结构确实与结构完全匹配。数据确实假设为 64 位机器,其中 double 必须在 8 字节边界上对齐(因此结构中有一个 4 字节孔);您将不得不为double 可以位于 4 字节边界上的机器调整数据。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* This is the type that will be simulated dynamically */
/*
struct simulated
{
    int     number;
    double  value;
    char    string[32];
};
*/

/* SOF structure.h */
typedef enum Type { INT, DOUBLE, STRING } Type;

typedef struct Descriptor
{
    size_t  offset;
    Type    type;
    size_t  type_size;
    size_t  array_dim;
    char    name[32];
} Descriptor;

typedef struct Structure
{
    size_t      size;
    char        name[32];
    Descriptor *details;
} Structure;

extern void   *allocate_structure(const Structure *structure);
extern void    deallocate_structure(void *structure);
extern void   *pointer_to_element(void *p, const Descriptor *d);
extern int     get_int_element(void *p, const Descriptor *d);
extern void    set_int_element(void *p, const Descriptor *d, int newval);
extern double  get_double_element(void *p, const Descriptor *d);
extern void    set_double_element(void *p, const Descriptor *d, double newval);
extern char   *get_string_element(void *p, const Descriptor *d);
extern void    set_string_element(void *p, const Descriptor *d, char *newval);
/* EOF structure.h */

static Descriptor details[] =
{
    {   0,  INT,    sizeof(int),     1, "number"    },
    {   8,  DOUBLE, sizeof(double),  1, "value"     },
    {  16,  STRING, sizeof(char),   32, "string"    },
};

static Structure simulated = { 48, "simulated", details };

void *allocate_structure(const Structure *structure)
{
    void *p = calloc(1, structure->size);
    return p;
}

void deallocate_structure(void *structure)
{
    free(structure);
}

void *pointer_to_element(void *p, const Descriptor *d)
{
    void *data = (char *)p + d->offset;
    return data;
}

int get_int_element(void *p, const Descriptor *d)
{
    assert(d->type == INT);
    int *v = pointer_to_element(p, d);
    return *v;
}

void set_int_element(void *p, const Descriptor *d, int newval)
{
    assert(d->type == INT);
    int *v = pointer_to_element(p, d);
    *v = newval;
}

double get_double_element(void *p, const Descriptor *d)
{
    assert(d->type == DOUBLE);
    double *v = pointer_to_element(p, d);
    return *v;
}

void set_double_element(void *p, const Descriptor *d, double newval)
{
    assert(d->type == DOUBLE);
    double *v = pointer_to_element(p, d);
    *v = newval;
}

char *get_string_element(void *p, const Descriptor *d)
{
    assert(d->type == STRING);
    char *v = pointer_to_element(p, d);
    return v;
}

void set_string_element(void *p, const Descriptor *d, char *newval)
{
    assert(d->type == STRING);
    assert(d->array_dim > 1);
    size_t len = strlen(newval);
    if (len > d->array_dim)
        len = d->array_dim - 1;
    char *v = pointer_to_element(p, d);
    memmove(v, newval, len);
    v[len] = '\0';
}

extern void other_function(void *p);

int main(void)
{
    void *sp = allocate_structure(&simulated);

    if (sp != 0)
    {
        set_int_element(sp, &simulated.details[0], 37);
        set_double_element(sp, &simulated.details[1], 3.14159);
        set_string_element(sp, &simulated.details[2], "Absolute nonsense");
        printf("Main (before):\n");
        printf("Integer: %d\n", get_int_element(sp, &simulated.details[0]));
        printf("Double:  %f\n", get_double_element(sp, &simulated.details[1]));
        printf("String:  %s\n", get_string_element(sp, &simulated.details[2]));
        other_function(sp);
        printf("Main (after):\n");
        printf("Integer: %d\n", get_int_element(sp, &simulated.details[0]));
        printf("Double:  %f\n", get_double_element(sp, &simulated.details[1]));
        printf("String:  %s\n", get_string_element(sp, &simulated.details[2]));

        deallocate_structure(sp);
    }
    return 0;
}

其他.c

这段代码对dynstruct.c中的结构描述材料一无所知;它知道模拟代码模拟的struct simulated。它打印它传递的数据并对其进行修改。

#include <stdio.h>
#include <string.h>

extern void other_function(void *p);

struct simulated
{
    int     number;
    double  value;
    char    string[32];
};

void other_function(void *p)
{
    struct simulated *s = (struct simulated *)p;

    printf("Other function:\n");
    printf("Integer: %d\n", s->number);
    printf("Double:  %f\n", s->value);
    printf("String:  %s\n", s->string);

    s->number *= 2;
    s->value  /= 2;
    strcpy(s->string, "Codswallop");
}

样本输出

Main (before):
Integer: 37
Double:  3.141590
String:  Absolute nonsense
Other function:
Integer: 37
Double:  3.141590
String:  Absolute nonsense
Main (after):
Integer: 74
Double:  1.570795
String:  Codswallop

显然,此代码尚未准备好生产。这是可以做什么的充分证明。您必须处理的一个问题是正确初始化StructureDescriptor 数据。你不能在那种代码中加入太多的断言。例如,我真的应该在get_double_element() 中有assert(d-&gt;size == sizeof(double);。包含assert(d-&gt;offset % sizeof(double) == 0); 以确保double 元素正确对齐也是明智的。或者你可能有一个validate_structure(const Structure *sp); 函数来完成所有这些验证检查。您需要一个函数void dump_structure(FILE *fp, const char *tag, const Structure *sp); 将定义的结构转储到标签前面的给定文件中,以帮助调试。等等。

这段代码是纯C;它不能被 C++ 编译器编译为 C++。没有足够的转换来满足 C++ 编译器。

【讨论】:

  • 如果服务器和客户端编译的设置不同,结构大小会有所不同..您还需要为服务器和客户端设置#pragma pack才能使用该结构..
  • @Gopalakrishnan:是的 - 有很多很多因素需要考虑。在同一台机器上进行 32 位编译与 64 位编译可能会导致不同的结构大小(除非您在结构定义中小心使用了诸如 uint32_t 之类的类型)。你不使用#pragma pack;这是非标准的。但是您确实需要担心结构中是否存在填充以及是否通过网络发送等。您可以通过仔细定义数据的发送方式(以及接收方式)来规避大多数这些问题,并将程序设计为正确打包/解包。
  • “创建包含与结构等效的信息的动态结构是可能的,但很困难。” - 你是怎样做的?我想将动态定义的结构传递给其他 C 代码(假设相同的编译器和其他设置),而不必从编译器复制结构内存布局例程。我不会在我的进程中访问这些结构的字段(只需初始化一次),所以方便的语法不是问题。
【解决方案2】:

不,在 C 中并非所有数据类型都必须在编译时知道。这就是它“真正快速”的原因。

【讨论】:

    【解决方案3】:

    另一种理论上的可能性是在运行时使用编译器库(如 libtcc)编译一些代码。

    虽然理论上非常吸引人(听起来确实像一个自我修改的应用程序 - 您的应用程序只需要为您的结构生成 C 代码并将其插入模板中,然后要求 libtcc 编译它,然后调用一些定义的函数在您的模板中使用该结构),此解决方案在实践中可能效果不佳。为什么 ?嗯,截至 2016 年,libtcc(以及整个 tcc 项目)的开发并不十分活跃,并且存在诸如 x86_64 等架构的问题。

    【讨论】:

      【解决方案4】:

      对于动态结构,答案是否定的。

      如果你知道什么数据进来,在 C++ 中,你可以使用重载的

      在 C 语言中,您可以将流转换为字符串,假设您知道传入的数据的长度并使用 sscanf 之类的函数,您可以读取数据。

      【讨论】:

      • 那会非常慢。固定消息传递的重点是速度......
      【解决方案5】:

      您无法定义源级结构,但您可以通过设置数据结构来存储名称/标记和要通信的数据的每个字段的偏移量,然后存储/根据那个在正确的偏移量处读取数据。确保将所有类型与sizeof(type) 的倍数的边界对齐,以实现可移植性。当然,除非您确定客户端和服务器将具有相同的数据表示(字节顺序和其他注意事项)并且确实需要直接访问的性能,否则我会编写适当的序列化和反序列化例程...

      【讨论】:

        【解决方案6】:

        根据 gerty3000 的回答,我创建了一个库。我已经从最终用户那里抽象了一些东西。这很难,但最终还是奏效了。如果有任何改进,我愿意接受建议。这是代码。

        type-machine.h // 定义类型和函数原型

        #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 <math.h>
        #include <string.h>
        #include <assert.h>
        
        #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 // 声明那些函数

        #include <Place/include/type-machine.h>
        #include <malloc.h>
        #include <stdio.h>
        
        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 // 测试....

        #include "network.h"
        #include <conio.h>
        
        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);
        }
        

        我仍然需要实现 short double 和其他一些功能,但它正在工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-24
          • 2022-01-05
          • 1970-01-01
          • 1970-01-01
          • 2019-10-25
          • 1970-01-01
          相关资源
          最近更新 更多