是否可以动态地定义在C结构 [英] Is it possible to dynamically define a struct in C

查看:102
本文介绍了是否可以动态地定义在C结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是pretty肯定这将最终成为一个非常明显的问题,这就是为什么我还没有找到它的信息。不过,我认为这是值得一问:)

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 :)

基本上,使用结构访问数据是真快。如果数据脱落在那里可以立即处理为结构形式的网络,这是pretty从性能上看甜蜜。

Basically, accessing data using a struct is really fast. If data comes off the network in a form where it can be immediately processed as a struct, this is pretty sweet from a performance point of view.

但是,它是可以动态地定义一个结构。可以在客户端和服务器应用程序协商数据流的格式,然后用该定义为结构?

However, is it possible to define a struct dynamically. Could a client and server app negotiate the format of the datastream and then use that definition as a struct?

如果不是,是否有这样做的更好的办法?

If not, is there a better way of doing it?

谢谢大家!

推荐答案

这是不可能的动态定义一个结构是相同的编译时间结构。

It isn't possible to dynamically define a struct that is identical to a compile-time struct.

这是可能的,但难度大,创建一个可以容纳相当于一个结构的信息的动态结构。对数据的访问比什么是可用在编译时不太方便。

It is possible, but difficult, to create dynamic structures that can contain the information equivalent to a struct. The access to the data is less convenient than what is available at compile-time.

其他所有分开,你可以使用 somestruct.not_seen_at_compile_time > - 方式> 标记,如果它不是在编译时定义的

All else apart, you cannot access a member somestruct.not_seen_at_compile_time using the . or -> notation if it was not defined at compile-time.

随着网络通信,还有其他问题需要解决 - 尤其是字节序。即,在电线上的数据可能会包括多字节(2,4,8)的整数,和MSB或LSB的将首先被发送,但是,如果一台机器是小端(IA-32,IA- 64,86/64),另一种是大端(SPARC,PPC几乎不从英特尔任何东西),那么数据将需要被改变。浮点格式也可以是有问题的。还有一些致力于定义如何将数据通过网络发送大量的标准 - 这是不平凡的。一些具体有:IP,TCP,UDP;其他都是一般的,如ASN.1。

With network communications, there are other issues to address - notably 'endianness'. That is, the data on the wire will probably include multi-byte (2, 4, 8) integers, and either the MSB or the LSB will be sent first, but if one machine is little-endian (IA-32, IA-64, x86/64) and the other is big-endian (SPARC, PPC, almost anything not from Intel), then the data will need to be transformed. Floating point formats can also be problematic. There are numerous standards dedicated to defining how data will be sent across the network - it is not trivial. Some are specific: IP, TCP, UDP; others are general, such as ASN.1.

然而,不能做动态数据结构'部分限制的东西 - 你必须对数据结构是什么事先约定,他们怎么会间preTED

However, the 'cannot do dynamic data structures' part limits things - you have to agree beforehand on what the data structures are, and how they will be interpreted.

gerty3000 问:

这是可能的,但难度大,创建一个可以容纳相当于一个结构信息的动态结构的 - 你怎么做呢?我想通过动态定义的结构切换到其他C code(假设相同的编译器和其它设置),而无需从编译器复制结构的内存布局套路。我不会访问我的进程中,这些结构的领域多(只是初始化一次即可),这样方便语法是不是一个问题。

It is possible, but difficult, to create dynamic structures that can contain the information equivalent to a struct. — How do you do that? I would like to pass dynamically-defined structs off to other C code (assume same compiler and other settings) without having to duplicate the struct memory layout routines from the compiler. I won't be accessing fields of these structs inside my process much (just initializing them once), so convenient syntax is not a concern.

您不能没有以某种形态或形式复制内存布局做到这一点。它可能不一定要完全相同,但它可能是最好的,如果它是。下面是一些示例code,显示大致可能怎么做。

You can't do it without duplicating the memory layout in some shape or form. It might not have to be exactly the same, but it is likely best if it is. Here's some sample code that shows roughly how it might be done.

这包含了基本结构操纵材料 - 结构来描述结构和(简单)的成员。处理全阵列(相对于串)将需要更多的工作,并且有化妆工作复制的一个很好的协议的其它类型进行管理。

This contains the basic structure manipulation material — structures to describe structures and (simple) members. Handling full arrays (as opposed to strings) would require more work, and there's a good deal of make-work replication to be managed for other types.

它还包含了一个的main()程序测试code。这使得以通话other_function(),这表明我在数据结构中定义的结构不完全匹配的结构。这些数据确实承担了64位计算机,其中双击必须是一个8字节边界上对齐(所以有结构中的4字节孔);你将不得不调整数据的机器,其中双击可以是4字节边界。

It also contains a main() program that tests the code. It makes a call to other_function(), which demonstrates that the structure I've defined in the data structures does match the structure exactly. The data does assume a 64-bit machine where double must be aligned on an 8-byte boundary (so there's a 4-byte hole in the structure); you will have to tweak the data for a machine where double can be on a 4-byte boundary.

#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

这code知道在一无所知的结构说明材料 dynstruct.c ;它知道模拟结构,仿真code模拟。它打印它传递的数据,并对其进行修改。

other.c

This code knows nothing about the structure description material in dynstruct.c; it knows about the struct simulated that the simulation code simulates. It prints the data it is passed and modifies it.

#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

显然,这code不是生产做好准备。这是什么可以做了充分论证。你必须应对的一个问题是正确初始化结构描述数据。你不能把太多的断言到那种code的。例如,我要真有断言(D&GT;大小==的sizeof(双); get_double_element()这也将是明智的,包括断言(D&GT;抵消%的sizeof(双)== 0); 来确保元素正确对齐或者你可能有一个 validate_structure(const的结构* SP);即做了所有这些验证检查函数你需要功能无效dump_structure(FILE * FP,为const char *标记,常量结构* SP); 来定义的结构转储到由标签pceded给定的文件$ p $,协助调试。等。

Clearly, this code is not production ready. It is a sufficient demonstration of what can be done. One issue you'd have to deal with is initializing the Structure and Descriptor data correctly. You can't put too many assertions into that sort of code. For example, I should really have assert(d->size == sizeof(double); in get_double_element(). It would also be sensible to include assert(d->offset % sizeof(double) == 0); to ensure that the double element is properly aligned. Or you might have a validate_structure(const Structure *sp); function that did all these validation checks. You'd need a function void dump_structure(FILE *fp, const char *tag, const Structure *sp); to dump the defined structure to the given file preceded by the tag, to assist in debugging. Etc.

这code是纯C;它是不是由C ++编译器和C ++编译。没有足够的演员,以满足C ++编译器。

This code is pure C; it is not compilable by a C++ compiler as C++. There aren't enough casts to satisfy a C++ compiler.

这篇关于是否可以动态地定义在C结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆