【发布时间】:2009-08-03 18:27:01
【问题描述】:
我正在编写一个轻量级序列化函数,需要在其中包含两个可变大小的数组。
- 我应该如何跟踪每个的大小?
- 我应该如何定义结构?
- 我是不是搞错了?
编辑:结果必须是连续的内存块
【问题讨论】:
我正在编写一个轻量级序列化函数,需要在其中包含两个可变大小的数组。
编辑:结果必须是连续的内存块
【问题讨论】:
这会解析为类似
typedef struct
{
size_t arr_size_1, arr_size_2;
char arr_1[0/*arr_size_1 + arr_size_2*/];
} ...;
大小应该在动态大小数据的前面,以便在扩展数组时它不会移动。
您的结构中不能有 2 个 unknown 大小的数组,因此您必须将它们折叠成一个,然后从第一个指针访问相对数据。
【讨论】:
typedef struct MyStruct_s
{
int variable_one_size;
void* variable_one_buf;
int variable_two_size;
void* variable_two_buf;
} MyStruct;
MyStruct* CreateMyStruct (int size_one, int size_two)
{
MyStruct* s = (MyStruct*)malloc (sizeof (MyStruct));
s->variable_one_size = size_one;
s->variable_one_buf = malloc (size_one);
s->variable_two_size = size_two;
s->variable_two_buf = malloc (size_two);
}
void FreeMyStruct (MyStruct* s)
{
free (s->variable_one_buf);
free (s->variable_two_buf);
free (s);
}
【讨论】:
由于数据在内存中应该是连续的,因此有必要分配一块大小合适的内存并或多或少地手动管理其内容。您可能最好创建一个包含“静态”信息和相关管理功能的结构,这些功能执行内存管理并提供对结构的“动态”成员的访问权限:
typedef struct _serial {
size_t sz_a;
size_t sz_b;
char data[1]; // "dummy" array as pointer to space at end of the struct
} serial;
serial* malloc_serial(size_t a, size_t b) {
serial *result;
// malloc more memory than just sizeof(serial), so that there
// is enough space "in" the data member for both of the variable arrays
result = malloc(sizeof(serial) - 1 + a + b);
if (result) {
result->sz_a = a;
result->sz_b = b;
}
return result;
}
// access the "arrays" in the struct:
char* access_a(serial *s) {
return &s->data[0];
}
char* access_b(serial *s) {
return &s->data[s->sz_a];
}
然后你可以这样做:
serial *s = ...;
memcpy(access_a(s), "hallo", 6);
access_a(s)[1] = 'e';
另外请注意,您不能只将一个serial 分配给另一个,您需要确保大小兼容并手动复制数据。
【讨论】:
为了序列化可变大小的数据,您必须有某种边界标记。边界标签可以是写在数据之前的大小,也可以是不允许出现在数据流中的特殊值,写在数据之后。
您选择哪一种取决于您存储的数据量,以及您是否正在优化输出流中的大小。预先存储大小通常更容易,因为您知道接收缓冲区的大小。如果不这样做,则必须在加载时逐渐调整缓冲区的大小。
【讨论】:
在某些方面,我会做 Dan Olson 这样的事情。然而:
1) 我将创建最终结构,方法是创建一个更简单的结构的两个实例,该结构只有一个变量数组。
2) 我会用 byte* 声明数组并使用 size_t 作为它的长度。
话虽如此,我仍然不完全清楚您要做什么。
编辑
如果您希望它在内存中连续,只需定义一个具有两个长度的结构。然后为要传递的两个块以及结构本身分配一个足够大的块。设置两个长度,然后立即复制两个块。我认为应该清楚长度如何足以使结构自描述。
【讨论】: