gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 16:25:15 26 4
gpt4 key购买 nike

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

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

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

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

谢谢大家!

最佳答案

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

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

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

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

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


你是怎么做到的?

gerty3000问:

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.

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

动态结构.c

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

它还包含一个测试代码的 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中的结构描述 Material 一无所知;它知道模拟代码模拟的 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->size == sizeof(double);。包含 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++ 编译器的要求。

关于c - 是否可以在C中动态定义结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6187908/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com