通常需要向可以在不同体系结构上运行的另一个程序发送或接收复杂数据结构,或者可以针对所讨论的数据结构的不同版本设计复杂数据结构。一个典型的例子是一个程序,它在退出时将其状态保存到文件中,然后在启动时将其读回。
“发送”功能通常首先将魔术标识符和版本写入文件或网络套接字,然后逐个(即串行)写入所有数据成员。如果遇到可变长度数组(例如字符串),它将写入一个长度后跟数据,或者它将写入数据后跟一个特殊的终止符。格式通常是XML或二进制; 在后一种情况下,htonl()宏集可能会派上用场。
‘receive’功能几乎相同:它将逐个读取所有项目。可变长度数组可以通过读取计数后跟数据来处理,也可以通过读取数据直到达到特殊终止符来处理。
由于这两个函数通常遵循与数据(结构)声明相同的模式,因此如果它们都可以从通用定义生成,那将是很好的。
X-Macros
一个Wikibookian表明,C语言程序设计/预处理器#X-宏被合并到这本书或章节。 讨论这种合并是否应该在讨论页面上进行。 |
X-Macros使用预处理器强制编译器多次编译同一段文本。有时会多次包含特殊文件(扩展名为.def)。例如,variables.def可能如下所示:
INT(值) INT(移位)
在这个例子中,C编程将如下所示:
... #define INT(var)int var; #include“variables.def” #undef INT ... printf(“version = 1 \ n”); #define INT(var)printf(#var“=%d \ n”,var); #include“variables.def” #undef INT ...
如果不希望多次包括单独的文件,则可以使用另一个宏。例如 :
#define VARIABLES INT(值)\ INT(移位)
该#包括 S可再与调用宏替换。
使用此方法,还可以传入(a)可以在值列表上操作的其他宏的名称。例如:
#define VAR_LIST(_)_(value)\ _(转移) ... #define VAR_INT_DECL(var)int var; VAR_LIST(VAR_INT_DECL) ... printf(“version = 1 \ n”); #define VAR_INT_PRINTF(var)printf(#var“=%d \ n”,var); VAR_LIST(VAR_INT_PRINTF) ...
这不需要重新定义宏,并且可以使代码更易于理解和维护。
X-Macros对于保持字符串和枚举类型之间的映射同步特别有用。
版本化序列化
假设我们要在上面的示例中添加其他变量,但我们仍然希望程序能够读取旧版本1文件。然后我们将一个版本参数和一个默认值参数添加到列表处理宏:
#define VAR_LIST(_)_(value,1,0)\ _(班次,1,0) _(掩模,2,0xffff) ... int inputVer; #define VAR_INT_DECL(var,varVer,default)int var; VAR_LIST(VAR_INT_DECL) ... scanf(“version =%d”,&inputVer); #define VAR_INT_SCN(var,varVer,default)if(varVer <= inputVer)scanf(#var“=%d”,&var); else var = default; VAR_LIST(VAR_INT_SCN) ... printf(“version = 2 \ n”); / *始终以最高已知版本输出* / #define VAR_INT_PRT(var,varVer,default)printf(#var“=%d \ n”,var); VAR_LIST(VAR_INT_PRT)
猜你想读:《C编程.高级C》5.协同程序
THE END