是否可以在C中动态定义结构

时间:2011-05-31 12:57:56

标签: c dynamic struct

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

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

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

如果没有,是否有更好的方法呢?

全部谢谢!

6 个答案:

答案 0 :(得分:19)

无法动态定义与编译时结构相同的结构。

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

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

通过网络通信,还有其他问题需要解决 - 尤其是'endianness'。也就是说,线上的数据可能包括多字节(2,4,8)整数,MSB或LSB将首先发送,但如果一台机器是小端(IA-32,IA-) 64,x86 / 64)和另一个是big-endian(SPARC,PPC,几乎所有不是来自英特尔),那么数据将需要转换。浮点格式也可能存在问题。有许多标准致力于定义如何通过网络发送数据 - 这不是微不足道的。一些是特定的:IP,TCP,UDP;其他是一般性的,例如ASN.1。

然而,'无法做动态数据结构'部分限制了事情 - 您必须事先就数据结构是什么以及如何解释它们达成一致。


你是怎么做到的?

gerty3000问道:

  

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

如果不以某种形状或形式复制内存布局,则无法执行此操作。它可能不一定完全相同,但如果是的话,它可能是最好的。这里有一些示例代码,大致显示了它的完成方式。

dynstruct.c

这包含基本结构操作材料 - 描述结构和(简单)成员的结构。处理完整数组(而不是字符串)需要更多的工作,并且需要为其他类型管理大量的make-work复制。

它还包含一个用于测试代码的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;
}

other.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数据。你不能在这种代码中加入过多的断言。例如,我应该在assert(d->size == sizeof(double);中拥有get_double_element()。包含assert(d->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 ++编译器。

答案 1 :(得分:9)

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

答案 2 :(得分:2)

另一个理论上的可能性是使用诸如libtcc之类的编译器库在运行时编译一些代码。

虽然理论上非常吸引人(它听起来像是一个自我修改的应用程序 - 你的应用程序只需要为你的结构生成C代码并将其插入模板中,然后请libtcc编译它然后调用一些定义的函数在你的模板中使用该结构),这个解决方案在实践中可能不会很好。为什么呢?好吧,截至2016年,libtcc(以及整个tcc项目)并没有非常积极地开发,并且存在x86_64等架构的问题。

答案 3 :(得分:1)

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

如果你知道有什么数据,在C ++中,你可以使用重载的&lt;&lt;在运算符中从流中读取数据..

在C中,您可以将流转换为字符串,假设您知道数据的长度,并使用像sscanf这样的函数,您可以读取数据。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

根据gerty3000的回答,我建了一个图书馆。我从最终用户那里抽象了一些东西。最后工作很难。如果有任何改进,我愿意接受消化。这就是代码。

type-machine.h //定义类型和函数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 <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和其他一些函数,但它正在工作。

相关问题