2

我正在将结构序列化为字节流。我的方法很简单:以小端顺序打包所有整数并复制包含空终止符的字符串。对方必须静态知道如何解包字节流,没有额外的元数据。

我的问题是,我不知道如何处理 NULL 指针?

我需要发送一些东西,因为流中没有额外的元数据。

我考虑了以下两个选项:

  1. 发送一个 '\0' 并使接收方在任何情况下都将其解释为 NULL

  2. 发送一个 '\0' 并使接收方在任何情况下都将其解释为 '\0' (分配一个字节)

  3. 发送一个表示 char* str == NULL 的特殊字符,例如 ETX、EOT、EM ?

你怎么看?

4

4 回答 4

4

看起来您当前正试图通过向接收端传递一个特殊字符来告诉接收端已到达序列化字符串的末尾。有一百万个案例会让你大吃一惊:

如果您的结构包含一个等于该特殊字符的字节怎么办。用另一个特殊字符转义它。如果您的结构包含一个字节序列,该字节序列等于您的转义字符后跟您的特殊字符,也要检查一下吗?

是的,这是可行的,但我认为这不是一个很好的解决方案,你必须编写一个解析器来查找转义字符,然后任何稍后查看代码的人都会花两个小时试图弄清楚发生了什么.

(tl;dr) 相反......只需使序列化字符串的前 32 位等于字符串中的字节数。每次序列化只需要 4 个字节,解决了所有问题,您不必编写解析器或担心特殊字符,并且会让下一个阅读您的代码的人更容易!

编辑

感谢 JeremyP,我刚刚意识到我并没有真正回答你的问题。为每个字符串发送其中一个:

结构 s_str { bool is_null; 整数大小;字符* str; };

如果它为空,只需将 is_null 设置为 true,您就不必担心其他两个。如果它的大小为零,请将 is_null 设置为 false 并将大小设置为零。如果 str 只包含一个 '\0',则将 is_null 设置为 false,将 size 设置为 1,并将 str[0] 设置为 '\0'

在我看来,这可能不是最节省内存的方式(你可能会以某种方式在某个地方保存一个字节),但你在做什么绝对很清楚,而且下一个出现的人会更喜欢这个。

于 2012-04-05T10:27:50.983 回答
2

不要这样做。使用一些额外的字节来存储长度并与您的数据字符串连接。接收端可以检查长度以了解它应该读入他的本地缓冲区的长度。

于 2012-04-05T10:35:27.887 回答
2

我建议您使用现有的库进行序列化。我现在能想到两个:tpl和 gwlib 的gwser.

关于tpl

您可以使用 tpl 快速轻松地存储和重新加载您的 C 数据。Tpl 适用于文件、内存缓冲区和文件描述符,因此它适合用作文件格式、IPC 消息格式或您需要存储和检索数据的任何场景。

关于gwlib,见链接,不是很冗长,但提供了一些使用示例。

于 2012-04-05T10:46:50.173 回答
2

这取决于协议中指针的重要性。如果指针很重要,即接收者需要知道如何重建结构,那么你需要发送一些东西。它可以是一个带有 0/非零的字节来指示存在,也可以是一个整数来指示指针所指向的字节数。

示例:struct Foo { int *arr, char *text }

Struct Foo 可以这样序列化:

<arr length><  arr   ><text length>< text >
  4 bytes    n bytes    4 bytes     n bytes
于 2012-04-05T10:40:23.233 回答