




已阅读5页,还剩64页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言的数据序列化64位平台C/C+开发注意事项在/en/l/上例出了28个在64位平台上使用C/C+开发的注意事项,对于进入64位时代的程序员应该去看看这28个事项,这些英文读物对于有C/C+功底的朋友读起来应该并不难,我估计大约20-30分钟可以精读完一篇(或者更快),下面是这28个注意事项的列表。相信对大家一点有帮助。Bhui2014 Lesson 01. What 64-bit systems are. Lesson 02. S数据结构的序列化是个很有用的东西。这几天在修改原来的资源管理模块,碰到从前做的几个数据文件解析的子模块,改得很烦,就重新思考序列化的方案了。Java 和 .Net 等,由于有完整的数据元信息,语言便提供了完善的序列化解决方案。C+ 对此在语言设计上有所缺陷,所以并没有特别好的,被所有人接受的方案。现存的 C+ serialization 方案多类似于 MFC 在二十年前的做法。而后,boost 提供了一个看起来更完备的方案( boost.serialization )。所谓更完备,我指的是非侵入。 boost 的解决方案用起来感觉更现代,看起来更漂亮。给人一种 不需要修改已有的 C+ 代码,就能把本不支持 serialize 的类加上这个特性 的心理快感。换句话说,就是这件事情我能做的,至于真正做的事情会碰到什么,那就不得而知了。好吧,老实说,我不喜欢用大量苦力(或是高智慧的结晶?)堆积起来的代码。不管是别人出的力,还是我自己出的。另外,我希望有一个 C 的解决方案,而不是 C+ 的。所以从昨天开始,就抽了点时间来搞定这件事。问题来至于 C/C+ 语言未提供类型元信息,那我们从根本上去解决好了。得到元信息的方案不在于使用奇怪的宏,我这个古板的 C 程序员,也用不起现代的 template 技术。其实自定义一下 C 的结构描述方式(创造个小语言),写个小程序去解析一下就行了。再用这个程序去生成 .h 文件,而供 serialization 库使用的元数据。如果暂不考虑让别的动态语言更方便的分析序列化后的数据(留给以后再扩展),其实,需要做序列化的对象仅仅只有两个数据类型:值类型和对其它类型的引用。对于值类型,我们可以简单的做内存拷贝,只需要知道值类型的长度。而引用,在内存中,则是简单的指针。序列化后则是相对数据块的偏移量。这里使用 base 1 ,这样可以允许 0 依旧表示空引用。我将引用分成两类,分别称呼为外引用,和内引用。所谓外引用,指这个引用指向一个不需要被序列化的数据块。在做序列化时,库会把这个外引用翻译成一个原子(通常表现为一个唯一的字符串)。数据展开时,再将原子还原成外引用。比如:文件或窗口句柄就可以被翻译成携带有文件名信息,或窗口标题信息的原子(这个取决于具体实现)。内引用:指引用的数据类型也为序列化模块所知。被引用的数据同样需要被加入序列化的数据块中。如果能正确的处理好所有的内引用关系,被引用的数据其实是内存地址无关的。在我定义的需求中,序列化模块应该尽可能的合并掉值相同的数据块。比如当字符串的值相同时,在序列化结果中就只应该存在一份。如果需要序列化一颗树,相同值的的叶子节点,或完全相同的子树,都应该被合并掉。另外,序列化模块应该正确的处理环状结构。比如可以正确的序列化一个循环链表,或是复杂的有向图。考虑到时间复杂度不能超过多项式时间。不考虑合并值相同且拓扑结构相同的有环图。(尽管理论上是可以合并它们的)由于有上面两个需求,proto buff 等现成的库是用不了的。btw, 还有一个小需求:数组类型的长度可以不固定,是由同个结构中另一个整型变量的值决定的。我花了一天一晚初步实现上面的东西。元信息的定义和处理并不复杂。序列化库的接口也很简洁:传入数据指针,数据类型的元信息,让库去填充一个数据块即可。其实,序列化的对象就是一个有向有环图。整个实现的难点在于对相同节点的合并。一开始没太想清楚,本着先做对再优化的原则,使用了个最苯的算法。(最坏情况下,可能有 O(N!) 的时间复杂度)即一开始并不合并相同节点。遍历处理完整个图以后,计算每个节点的 hash 值,然后排序,去掉完全相同的节点,并反向修改引用它们的节点。然后反复这个过程,直到有效节点数不再减少。最后再把所有有效节点放在输出流中,最终调整一下所有的内部引用。今天和同事讨论了一下,觉得可以改进这个算法。创建两个集合,一个为有效节点的原子集合,另一个为原始数据块的引用集合。先在遍历原始数据块,同时把原始数据块的每个节点逐个加入原始数据块集合中(相同的原始指针会在这个步骤被去掉),并生成临时对象方便我们做进一步处理。这个临时对象上,可以附加遍历状态标记,hash 值,长度,等等信息。当一个节点上的所有引用均被处理完,这个节点的数据可以转换为一个原子,加入有效节点的原子集合。当碰到成环的情况,只能是由于当前节点引用了一个先前并没有处理完的节点。这个时候,由于环的存在,那个导致环出现的先前的未处理完的节点,可以肯定不会被公用了。 所以,我们可以认为,此节点可以直接被转换为一个原子,加入有效节点集合。换句话说,以后也不会再出现另一个数据块和这个原子完全相同。用此算法,我们可以只通过一次遍历,找到所有的有效节点,并合并掉一切值相同的节点。最后,一次性将有效节点拼成一个连续的数据块,并修正引用记录即可。实现的要点在于,要定义一个内存堆,并从堆中申请序列化过程中使用到的临时内存。然后在序列化完成后直接清除整个堆。如果不这样做,整个过程中的各个零碎而繁杂的数据结构的生命期管理会要命的。同时,需要定义一个 context 结构,用于记录繁杂的序列化流程中的各种数据。并使用 longjmp 做异常处理(主要用于处理用户提供的 buffer 空间不够的情况)。这会使程序变得很简洁。至于代码,目前还没完全写完。缺少序列化结果展开的部分,以及数据描述语言的解析器(测试代码暂时用手工解析)。不过序列化部分基本可用了。加上测试代码,大约用 500 行搞定。看来还算是个小玩意。写下本文,记录下思路。31 号 补充:以上对图的相同节点合并算法,是有缺陷的。在处理环问题时,不能做最大可能的合并。比如: +-+A - B - C - D+-+在此种情况下,虽然 A 和 D 节点的拓扑结构类似,如果值相等,是可以被合并的。但此算法对此无能为力。不过考虑到实现的简洁和不错的时间性能,可以容忍这个缺陷。来自:数据结构的序列化是个很有用的东西。这几天在修改原来的资源管理模块,碰到从前做的几个数据文件解析的子模块,改得很烦,就重新思考序列化的方案了。Java 和 .Net 等,由于有完整的数据元信息,语言便提供了完善的序列化解决方案。C+ 对此在语言设计上有所缺陷,所以并没有特别好的,被所有人接受的方案。现存的 C+ serialization 方案多类似于 MFC 在二十年前的做法。而后,boost 提供了一个看起来更完备的方案( boost.serialization )。所谓更完备,我指的是非侵入。 boost 的解决方案用起来感觉更现代,看起来更漂亮。给人一种 不需要修改已有的 C+ 代码,就能把本不支持 serialize 的类加上这个特性 的心理快感。换句话说,就是这件事情我能做的,至于真正做的事情会碰到什么,那就不得而知了。好吧,老实说,我不喜欢用大量苦力(或是高智慧的结晶?)堆积起来的代码。不管是别人出的力,还是我自己出的。另外,我希望有一个 C 的解决方案,而不是 C+ 的。所以从昨天开始,就抽了点时间来搞定这件事。问题来至于 C/C+ 语言未提供类型元信息,那我们从根本上去解决好了。得到元信息的方案不在于使用奇怪的宏,我这个古板的 C 程序员,也用不起现代的 template 技术。其实自定义一下 C 的结构描述方式(创造个小语言),写个小程序去解析一下就行了。再用这个程序去生成 .h 文件,而供 serialization 库使用的元数据。如果暂不考虑让别的动态语言更方便的分析序列化后的数据(留给以后再扩展),其实,需要做序列化的对象仅仅只有两个数据类型:值类型和对其它类型的引用。对于值类型,我们可以简单的做内存拷贝,只需要知道值类型的长度。而引用,在内存中,则是简单的指针。序列化后则是相对数据块的偏移量。这里使用 base 1 ,这样可以允许 0 依旧表示空引用。我将引用分成两类,分别称呼为外引用,和内引用。所谓外引用,指这个引用指向一个不需要被序列化的数据块。在做序列化时,库会把这个外引用翻译成一个原子(通常表现为一个唯一的字符串)。数据展开时,再将原子还原成外引用。比如:文件或窗口句柄就可以被翻译成携带有文件名信息,或窗口标题信息的原子(这个取决于具体实现)。内引用:指引用的数据类型也为序列化模块所知。被引用的数据同样需要被加入序列化的数据块中。如果能正确的处理好所有的内引用关系,被引用的数据其实是内存地址无关的。在我定义的需求中,序列化模块应该尽可能的合并掉值相同的数据块。比如当字符串的值相同时,在序列化结果中就只应该存在一份。如果需要序列化一颗树,相同值的的叶子节点,或完全相同的子树,都应该被合并掉。另外,序列化模块应该正确的处理环状结构。比如可以正确的序列化一个循环链表,或是复杂的有向图。考虑到时间复杂度不能超过多项式时间。不考虑合并值相同且拓扑结构相同的有环图。(尽管理论上是可以合并它们的)由于有上面两个需求,proto buff 等现成的库是用不了的。btw, 还有一个小需求:数组类型的长度可以不固定,是由同个结构中另一个整型变量的值决定的。我花了一天一晚初步实现上面的东西。元信息的定义和处理并不复杂。序列化库的接口也很简洁:传入数据指针,数据类型的元信息,让库去填充一个数据块即可。其实,序列化的对象就是一个有向有环图。整个实现的难点在于对相同节点的合并。一开始没太想清楚,本着先做对再优化的原则,使用了个最苯的算法。(最坏情况下,可能有 O(N!) 的时间复杂度)即一开始并不合并相同节点。遍历处理完整个图以后,计算每个节点的 hash 值,然后排序,去掉完全相同的节点,并反向修改引用它们的节点。然后反复这个过程,直到有效节点数不再减少。最后再把所有有效节点放在输出流中,最终调整一下所有的内部引用。今天和同事讨论了一下,觉得可以改进这个算法。创建两个集合,一个为有效节点的原子集合,另一个为原始数据块的引用集合。先在遍历原始数据块,同时把原始数据块的每个节点逐个加入原始数据块集合中(相同的原始指针会在这个步骤被去掉),并生成临时对象方便我们做进一步处理。这个临时对象上,可以附加遍历状态标记,hash 值,长度,等等信息。当一个节点上的所有引用均被处理完,这个节点的数据可以转换为一个原子,加入有效节点的原子集合。当碰到成环的情况,只能是由于当前节点引用了一个先前并没有处理完的节点。这个时候,由于环的存在,那个导致环出现的先前的未处理完的节点,可以肯定不会被公用了。 所以,我们可以认为,此节点可以直接被转换为一个原子,加入有效节点集合。换句话说,以后也不会再出现另一个数据块和这个原子完全相同。用此算法,我们可以只通过一次遍历,找到所有的有效节点,并合并掉一切值相同的节点。最后,一次性将有效节点拼成一个连续的数据块,并修正引用记录即可。实现的要点在于,要定义一个内存堆,并从堆中申请序列化过程中使用到的临时内存。然后在序列化完成后直接清除整个堆。如果不这样做,整个过程中的各个零碎而繁杂的数据结构的生命期管理会要命的。同时,需要定义一个 context 结构,用于记录繁杂的序列化流程中的各种数据。并使用 longjmp 做异常处理(主要用于处理用户提供的 buffer 空间不够的情况)。这会使程序变得很简洁。至于代码,目前还没完全写完。缺少序列化结果展开的部分,以及数据描述语言的解析器(测试代码暂时用手工解析)。不过序列化部分基本可用了。加上测试代码,大约用 500 行搞定。看来还算是个小玩意。写下本文,记录下思路。31 号 补充:以上对图的相同节点合并算法,是有缺陷的。在处理环问题时,不能做最大可能的合并。比如: +-+A - B - C - D+-+在此种情况下,虽然 A 和 D 节点的拓扑结构类似,如果值相等,是可以被合并的。但此算法对此无能为力。不过考虑到实现的简洁和不错的时间性能,可以容忍这个缺陷。来自:数据结构的序列化是个很有用的东西。这几天在修改原来的资源管理模块,碰到从前做的几个数据文件解析的子模块,改得很烦,就重新思考序列化的方案了。Java 和 .Net 等,由于有完整的数据元信息,语言便提供了完善的序列化解决方案。C+ 对此在语言设计上有所缺陷,所以并没有特别好的,被所有人接受的方案。现存的 C+ serialization 方案多类似于 MFC 在二十年前的做法。而后,boost 提供了一个看起来更完备的方案( boost.serialization )。所谓更完备,我指的是非侵入。 boost 的解决方案用起来感觉更现代,看起来更漂亮。给人一种 不需要修改已有的 C+ 代码,就能把本不支持 serialize 的类加上这个特性 的心理快感。换句话说,就是这件事情我能做的,至于真正做的事情会碰到什么,那就不得而知了。好吧,老实说,我不喜欢用大量苦力(或是高智慧的结晶?)堆积起来的代码。不管是别人出的力,还是我自己出的。另外,我希望有一个 C 的解决方案,而不是 C+ 的。所以从昨天开始,就抽了点时间来搞定这件事。问题来至于 C/C+ 语言未提供类型元信息,那我们从根本上去解决好了。得到元信息的方案不在于使用奇怪的宏,我这个古板的 C 程序员,也用不起现代的 template 技术。其实自定义一下 C 的结构描述方式(创造个小语言),写个小程序去解析一下就行了。再用这个程序去生成 .h 文件,而供 serialization 库使用的元数据。如果暂不考虑让别的动态语言更方便的分析序列化后的数据(留给以后再扩展),其实,需要做序列化的对象仅仅只有两个数据类型:值类型和对其它类型的引用。对于值类型,我们可以简单的做内存拷贝,只需要知道值类型的长度。而引用,在内存中,则是简单的指针。序列化后则是相对数据块的偏移量。这里使用 base 1 ,这样可以允许 0 依旧表示空引用。我将引用分成两类,分别称呼为外引用,和内引用。所谓外引用,指这个引用指向一个不需要被序列化的数据块。在做序列化时,库会把这个外引用翻译成一个原子(通常表现为一个唯一的字符串)。数据展开时,再将原子还原成外引用。比如:文件或窗口句柄就可以被翻译成携带有文件名信息,或窗口标题信息的原子(这个取决于具体实现)。内引用:指引用的数据类型也为序列化模块所知。被引用的数据同样需要被加入序列化的数据块中。如果能正确的处理好所有的内引用关系,被引用的数据其实是内存地址无关的。在我定义的需求中,序列化模块应该尽可能的合并掉值相同的数据块。比如当字符串的值相同时,在序列化结果中就只应该存在一份。如果需要序列化一颗树,相同值的的叶子节点,或完全相同的子树,都应该被合并掉。另外,序列化模块应该正确的处理环状结构。比如可以正确的序列化一个循环链表,或是复杂的有向图。考虑到时间复杂度不能超过多项式时间。不考虑合并值相同且拓扑结构相同的有环图。(尽管理论上是可以合并它们的)由于有上面两个需求,proto buff 等现成的库是用不了的。btw, 还有一个小需求:数组类型的长度可以不固定,是由同个结构中另一个整型变量的值决定的。我花了一天一晚初步实现上面的东西。元信息的定义和处理并不复杂。序列化库的接口也很简洁:传入数据指针,数据类型的元信息,让库去填充一个数据块即可。其实,序列化的对象就是一个有向有环图。整个实现的难点在于对相同节点的合并。一开始没太想清楚,本着先做对再优化的原则,使用了个最苯的算法。(最坏情况下,可能有 O(N!) 的时间复杂度)即一开始并不合并相同节点。遍历处理完整个图以后,计算每个节点的 hash 值,然后排序,去掉完全相同的节点,并反向修改引用它们的节点。然后反复这个过程,直到有效节点数不再减少。最后再把所有有效节点放在输出流中,最终调整一下所有的内部引用。今天和同事讨论了一下,觉得可以改进这个算法。创建两个集合,一个为有效节点的原子集合,另一个为原始数据块的引用集合。先在遍历原始数据块,同时把原始数据块的每个节点逐个加入原始数据块集合中(相同的原始指针会在这个步骤被去掉),并生成临时对象方便我们做进一步处理。这个临时对象上,可以附加遍历状态标记,hash 值,长度,等等信息。当一个节点上的所有引用均被处理完,这个节点的数据可以转换为一个原子,加入有效节点的原子集合。当碰到成环的情况,只能是由于当前节点引用了一个先前并没有处理完的节点。这个时候,由于环的存在,那个导致环出现的先前的未处理完的节点,可以肯定不会被公用了。 所以,我们可以认为,此节点可以直接被转换为一个原子,加入有效节点集合。换句话说,以后也不会再出现另一个数据块和这个原子完全相同。用此算法,我们可以只通过一次遍历,找到所有的有效节点,并合并掉一切值相同的节点。最后,一次性将有效节点拼成一个连续的数据块,并修正引用记录即可。实现的要点在于,要定义一个内存堆,并从堆中申请序列化过程中使用到的临时内存。然后在序列化完成后直接清除整个堆。如果不这样做,整个过程中的各个零碎而繁杂的数据结构的生命期管理会要命的。同时,需要定义一个 context 结构,用于记录繁杂的序列化流程中的各种数据。并使用 longjmp 做异常处理(主要用于处理用户提供的 buffer 空间不够的情况)。这会使程序变得很简洁。至于代码,目前还没完全写完。缺少序列化结果展开的部分,以及数据描述语言的解析器(测试代码暂时用手工解析)。不过序列化部分基本可用了。加上测试代码,大约用 500 行搞定。看来还算是个小玩意。写下本文,记录下思路。31 号 补充:以上对图的相同节点合并算法,是有缺陷的。在处理环问题时,不能做最大可能的合并。比如: +-+A - B - C - D+-+在此种情况下,虽然 A 和 D 节点的拓扑结构类似,如果值相等,是可以被合并的。但此算法对此无能为力。不过考虑到实现的简洁和不错的时间性能,可以容忍这个缺陷。来自:数据结构的序列化是个很有用的东西。这几天在修改原来的资源管理模块,碰到从前做的几个数据文件解析的子模块,改得很烦,就重新思考序列化的方案了。Java 和 .Net 等,由于有完整的数据元信息,语言便提供了完善的序列化解决方案。C+ 对此在语言设计上有所缺陷,所以并没有特别好的,被所有人接受的方案。现存的 C+ serialization 方案多类似于 MFC 在二十年前的做法。而后,boost 提供了一个看起来更完备的方案( boost.serialization )。所谓更完备,我指的是非侵入。 boost 的解决方案用起来感觉更现代,看起来更漂亮。给人一种 不需要修改已有的 C+ 代码,就能把本不支持 serialize 的类加上这个特性 的心理快感。换句话说,就是这件事情我能做的,至于真正做的事情会碰到什么,那就不得而知了。好吧,老实说,我不喜欢用大量苦力(或是高智慧的结晶?)堆积起来的代码。不管是别人出的力,还是我自己出的。另外,我希望有一个 C 的解决方案,而不是 C+ 的。所以从昨天开始,就抽了点时间来搞定这件事。问题来至于 C/C+ 语言未提供类型元信息,那我们从根本上去解决好了。得到元信息的方案不在于使用奇怪的宏,我这个古板的 C 程序员,也用不起现代的 template 技术。其实自定义一下 C 的结构描述方式(创造个小语言),写个小程序去解析一下就行了。再用这个程序去生成 .h 文件,而供 serialization 库使用的元数据。如果暂不考虑让别的动态语言更方便的分析序列化后的数据(留给以后再扩展),其实,需要做序列化的对象仅仅只有两个数据类型:值类型和对其它类型的引用。对于值类型,我们可以简单的做内存拷贝,只需要知道值类型的长度。而引用,在内存中,则是简单的指针。序列化后则是相对数据块的偏移量。这里使用 base 1 ,这样可以允许 0 依旧表示空引用。我将引用分成两类,分别称呼为外引用,和内引用。所谓外引用,指这个引用指向一个不需要被序列化的数据块。在做序列化时,库会把这个外引用翻译成一个原子(通常表现为一个唯一的字符串)。数据展开时,再将原子还原成外引用。比如:文件或窗口句柄就可以被翻译成携带有文件名信息,或窗口标题信息的原子(这个取决于具体实现)。内引用:指引用的数据类型也为序列化模块所知。被引用的数据同样需要被加入序列化的数据块中。如果能正确的处理好所有的内引用关系,被引用的数据其实是内存地址无关的。在我定义的需求中,序列化模块应该尽可能的合并掉值相同的数据块。比如当字符串的值相同时,在序列化结果中就只应该存在一份。如果需要序列化一颗树,相同值的的叶子节点,或完全相同的子树,都应该被合并掉。另外,序列化模块应该正确的处理环状结构。比如可以正确的序列化一个循环链表,或是复杂的有向图。考虑到时间复杂度不能超过多项式时间。不考虑合并值相同且拓扑结构相同的有环图。(尽管理论上是可以合并它们的)由于有上面两个需求,proto buff 等现成的库是用不了的。btw, 还有一个小需求:数组类型的长度可以不固定,是由同个结构中另一个整型变量的值决定的。我花了一天一晚初步实现上面的东西。元信息的定义和处理并不复杂。序列化库的接口也很简洁:传入数据指针,数据类型的元信息,让库去填充一个数据块即可。其实,序列化的对象就是一个有向有环图。整个实现的难点在于对相同节点的合并。一开始没太想清楚,本着先做对再优化的原则,使用了个最苯的算法。(最坏情况下,可能有 O(N!) 的时间复杂度)即一开始并不合并相同节点。遍历处理完整个图以后,计算每个节点的 hash 值,然后排序,去掉完全相同的节点,并反向修改引用它们的节点。然后反复这个过程,直到有效节点数不再减少。最后再把所有有效节点放在输出流中,最终调整一下所有的内部引用。今天和同事讨论了一下,觉得可以改进这个算法。创建两个集合,一个为有效节点的原子集合,另一个为原始数据块的引用集合。先在遍历原始数据块,同时把原始数据块的每个节点逐个加入原始数据块集合中(相同的原始指针会在这个步骤被去掉),并生成临时对象方便我们做进一步处理。这个临时对象上,可以附加遍历状态标记,hash 值,长度,等等信息。当一个节点上的所有引用均被处理完,这个节点的数据可以转换为一个原子,加入有效节点的原子集合。当碰到成环的情况,只能是由于当前节点引用了一个先前并没有处理完的节点。这个时候,由于环的存在,那个导致环出现的先前的未处理完的节点,可以肯定不会被公用了。 所以,我们可以认为,此节点可以直接被转换为一个原子,加入有效节点集合。换句话说,以后也不会再出现另一个数据块和这个原子完全相同。用此算法,我们可以只通过一次遍历,找到所有的有效节点,并合并掉一切值相同的节点。最后,一次性将有效节点拼成一个连续的数据块,并修正引用记录即可。实现的要点在于,要定义一个内存堆,并从堆中申请序列化过程中使用到的临时内存。然后在序列化完成后直接清除整个堆。如果不这样做,整个过程中的各个零碎而繁杂的数据结构的生命期管理会要命的。同时,需要定义一个 context 结构,用于记录繁杂的序列化流程中的各种数据。并使用 longjmp 做异常处理(主要用于处理用户提供的 buffer 空间不够的情况)。这会使程序变得很简洁。至于代码,目前还没完全写完。缺少序列化结果展开的部分,以及数据描述语言的解析器(测试代码暂时用手工解析)。不过序列化部分基本可用了。加上测试代码,大约用 500 行搞定。看来还算是个小玩意。写下本文,记录下思路。31 号 补充:以上对图的相同节点合并算法,是有缺陷的。在处理环问题时,不能做最大可能的合并。比如: +-+A - B - C - D+-+在此种情况下,虽然 A 和 D 节点的拓扑结构类似,如果值相等,是可以被合并的。但此算法对此无能为力。不过考虑到实现的简洁和不错的时间性能,可以容忍这个缺陷。来自:数据结构的序列化是个很有用的东西。这几天在修改原来的资源管理模块,碰到从前做的几个数据文件解析的子模块,改得很烦,就重新思考序列化的方案了。Java 和 .Net 等,由于有完整的数据元信息,语言便提供了完善的序列化解决方案。C+ 对此在语言设计上有所缺陷,所以并没有特别好的,被所有人接受的方案。现存的 C+ serialization 方案多类似于 MFC 在二十年前的做法。而后,boost 提供了一个看起来更完备的方案( boost.serialization )。所谓更完备,我指的是非侵入。 boost 的解决方案用起来感觉更现代,看起来更漂亮。给人一种 不需要修改已有的 C+ 代码,就能把本不支持 serialize 的类加上这个特性 的心理快感。换句话说,就是这件事情我能做的,至于真正做的事情会碰到什么,那就不得而知了。好吧,老实说,我不喜欢用大量苦力(或是高智慧的结晶?)堆积起来的代码。不管是别人出的力,还是我自己出的。另外,我希望有一个 C 的解决方案,而不是 C+ 的。所以从昨天开始,就抽了点时间来搞定这件事。问题来至于 C/C+ 语言未提供类型元信息,那我们从根本上去解决好了。得到元信息的方案不在于使用奇怪的宏,我这个古板的 C 程序员,也用不起现代的 template 技术。其实自定义一下 C 的结构描述方式(创造个小语言),写个小程序去解析一下就行了。再用这个程序去生成 .h 文件,而供 serialization 库使用的元数据。如果暂不考虑让别的动态语言更方便的分析序列化后的数据(留给以后再扩展),其实,需要做序列化的对象仅仅只有两个数据类型:值类型和对其它类型的引用。对于值类型,我们可以简单的做内存拷贝,只需要知道值类型的长度。而引用,在内存中,则是简单的指针。序列化后则是相对数据块的偏移量。这里使用 base 1 ,这样可以允许 0 依旧表示空引用。我将引用分成两类,分别称呼为外引用,和内引用。所谓外引用,指这个引用指向一个不需要被序列化的数据块。在做序列化时,库会把这个外引用翻译成一个原子(通常表现为一个唯一的字符串)。数据展开时,再将原子还原成外引用。比如:文件或窗口句柄就可以被翻译成携带有文件名信息,或窗口标题信息的原子(这个取决于具体实现)。内引用:指引用的数据类型也为序列化模块所知。被引用的数据同样需要被加入序列化的数据块中。如果能正确的处理好所有的内引用关系,被引用的数据其实是内存地址无关的。在我定义的需求中,序列化模块应该尽可能的合并掉值相同的数据块。比如当字符串的值相同时,在序列化结果中就只应该存在一份。如果需要序列化一颗树,相同值的的叶子节点,或完全相同的子树,都应该被合并掉。另外,序列化模块应该正确的处理环状结构。比如可以正确的序列化一个循环链表,或是复杂的有向图。考虑到时间复杂度不能超过多项式时间。不考虑合并值相同且拓扑结
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025企业间借款的合同协议书
- 2025年度品牌形象设计委托合同协议书范本
- 租房拆迁协议书
- 公司和公司签合作协议书
- 以抵债协议书
- 婚前协议书是否有效
- 公众协议书格式
- 离婚协议书抚养费逾期
- 销售合同三方协议书
- 不签婚内协议书
- 《茉莉花》音乐课件
- 2025年云南省职教高考电工技术类《电工基础理论知识》考试复习题库(含答案)
- 工厂交叉作业安全管理协议书(2篇)
- 外墙真石漆工程安全文明施工保证措施及环境保护体系和保证措施
- 品管圈PDCA改善案例-产科联合多部门降低阴道分娩产后出血发生率
- 矿井火灾防治理论与技术课件
- 【MOOC】生命的教育-浙江大学 中国大学慕课MOOC答案
- 中国非遗文化鱼灯介绍介绍2
- NB/T 11127-2023在用钢丝绳芯输送带报废检测技术规范
- 食品检测实验室操作规程
- 急性ST段抬高心肌梗死临床路径表单
评论
0/150
提交评论