- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我很确定这最终会成为一个非常明显的问题,这就是为什么我没有找到太多关于它的信息。不过,我认为这值得一问 :)
基本上,使用结构访问数据非常快。如果数据以可以立即作为结构处理的形式离开网络,从性能的角度来看,这是非常好的。
但是,是否可以动态定义结构。客户端和服务器应用程序能否协商数据流的格式,然后将该定义用作结构?
如果没有,是否有更好的方法?
谢谢大家!
最佳答案
无法动态定义与编译时结构相同的结构。
创建可以包含与结构等效的信息的动态结构是可能的,但很困难。对数据的访问不如编译时可用的方便。
除此之外,如果未定义,则不能使用点 .
或箭头 ->
表示法访问成员 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。
但是,“不能做动态数据结构”部分限制了一些事情——你必须事先就数据结构是什么以及它们将如何被解释达成一致。
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.
如果不以某种形状或形式复制内存布局,就无法做到这一点。它可能不必完全相同,但最好是完全相同。下面是一些示例代码,大致显示了它可能如何完成。
这包含基本的结构操作 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;
}
这段代码对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
很明显,这段代码还没有准备好投入生产。这足以证明可以做什么。您必须处理的一个问题是正确初始化 Structure
和 Descriptor
数据。您不能在这类代码中放入太多断言。例如,我真的应该在 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/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!