【问题标题】:Binary serialization of variable length data and zero length arrays, is it safe?可变长度数据和零长度数组的二进制序列化,安全吗?
【发布时间】:2012-04-04 21:34:51
【问题描述】:

我做了一些研究,但找不到明确的赞同或反对意见。

我想要的是一个固定大小的结构+可变长度的部分,这样序列化就可以用简单且不易出错的方式来表达。

struct serialized_data
{
    int len;
    int type;
    char variable_length_text[0];
};

然后:

serialize_data buff = (serialize_data*)malloc(sizeof(serialize_data)+5);
buff->len=5;
buff->type=1;
memcpy(buff->variable_length_text, "abcd", 5);

很遗憾,我找不到 MSVC、GCC、CLang 等是否可以使用它。

也许有更好的方法来达到同样的效果?

我真的不想要那些丑陋的演员:

memcpy((char*)(((char*)buffer)+sizeof(serialize_data)), "abcd", 5);

【问题讨论】:

  • 应该是char variable_length_text[1];,但是是的,肯定有更好的方法来实现同样的目标。
  • 选择一种语言。你对 C++ 还是 C 感兴趣?
  • 您可能会发现这篇文章很有用。不回答可移植性问题,但确实对这种模式提供了一些见解blogs.msdn.com/b/oldnewthing/archive/2004/08/26/220873.aspx
  • @ildjarn 从 C99 开始,长度为 0 的数组不应该是合法的吗?
  • @JaredPar:C99 中不允许使用零长度数组。您正在考虑灵活的数组成员,其定义没有像char member[]; 这样的长度。它们必须作为 struct 中的最后一个成员出现,并且仅在 C99 中允许使用。并非所有编译器(著名的 MSVC)都符合 C99,因此使用长度为 1 的数组更便于移植,尽管这会使大小计算变得复杂。

标签: c++ c serialization


【解决方案1】:

此程序使用零长度数组。这不是 C,而是 GNU 扩展。

http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

C89 中的一个常见习语,称为 struct hack,用于:

struct serialized_data
{
    int len;
    int type;
    char variable_length_text[1];
}; 

不幸的是,它作为灵活数组的常见用途并不严格遵守。

C99 提供了类似的功能来执行相同的任务:一个称为灵活数组成员的功能。 这是标准中的一个示例(C99,6.7.2.1p17)

struct s { int n; double d[]; };
int m = 12;  // some value
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

【讨论】:

  • 我可以使用 C99 方式并且可以安全地在 MSVC7/8/9、GCC 和 Clang 上运行吗?
  • gcc 和 clang 支持 C99,但 MSVC 不支持。 struct hack 虽然不严格遵守,但很常见,应该考虑用于 C89 编译器。
猜你喜欢
  • 2015-04-19
  • 2012-02-27
  • 2011-11-11
  • 1970-01-01
  • 2012-09-06
  • 2014-07-27
  • 1970-01-01
  • 2014-07-25
相关资源
最近更新 更多