我正在研究C中的项目。我观察到可以根据某些规则自动生成大量代码。即。如果我只指定C结构,则可以自动生成代码。我知道可以做到,但我之前没有做过。如果经验丰富的C程序员能够以最少的工程努力提供某些指导或分享他们如何做这些事情的经验,那将是很好的。
编辑:非常具体,我是否需要在C中编写自定义解析器来完成所有这些或者是否有更简单的方法来解决这个问题?
答案 0 :(得分:2)
我看到的一种有效方法是使用宏(一种经常讨厌的工具)。宏有两个功能可以帮助简化生活,单个哈希'#'可以将参数转换为字符串,即#_name
将被翻译为"fieldName1"
和双哈希'##'它将参数与其他事物连接起来,而这些事物又可以扩展新事物,即STRUCT_##_type##_str
将被翻译成STRUCT_int_str
,将被翻译成"%d"
首先将结构或“描述”包装在宏中,即包装到自己的文件中(-struct.def)
STRUCT_BEGIN(s_my_struct)
STRUCT_FIELD(int, fieldName1)
STRUCT_FIELD(int, fieldName2)
STRUCT_FIELD(int, fieldName3)
STRUCT_END(s_my_struct)
// Note that you can add more structs here and all will automatically get defined and get the print function implemented
然后,人们可以在想要声明或实现应该处理结构的东西的地方不同地定义宏。即。
#define STRUCT_BEGIN(_name) struct _name {
#define STRUCT_END(_name) };
#define STRUCT_FIELD(_type, _name) _type _name;
#include "the-struct.def"
// then undef them
#undef STRUCT_BEGIN
#undef STRUCT_END
#undef STRUCT_FIELD
并创建一个打印结构
的函数#define STRUCT_BEGIN(_name) void print_ ## _name(struct _name *s) {
#define STRUCT_END(_name) }
#define STRUCT_FIELD(_type, _name) printf("%s = " STRUCT_##_type##_str "\n", #_name, s->_name);
#define STRUCT_int_str "%d" /* this is to output an int */
// add more types...
#include "the-struct.def"
// then undef them
#undef STRUCT_BEGIN
#undef STRUCT_END
#undef STRUCT_FIELD
#undef STRUCT_int_str
其他用途可以是自动生成函数,即交换字节等。
在这里做了一个小例子作为要点https://gist.github.com/3786323
答案 1 :(得分:2)
在C语言中进行元编程的一种相对传统的方法是采用类似X macros的技术。
本质上,不是使用普通的C结构声明,而是使用宏完全定义结构,类似这样的
BEGIN_STRUCT(pointf)
FIELD(float, x)
FIELD(float, y)
END_STRUCT(pointf)
并将这些定义放在一个头文件中,不存在多重包含的保护。
然后,对于您需要生成的每段代码(包括基本结构),#define
每个元语言宏,#include
定义标题和#undef
元语言宏再次:
#define BEGIN_STRUCT(N) struct N {
#define FIELD(T,N) T N;
#define END_STRUCT(N) }
#include "definitions.h"
#undef BEGIN_STRUCT
#undef FIELD
#undef END_STRUCT
答案 2 :(得分:2)
简单的部分与1:1语法替换有关。
除了1:1语法替换之外,困难的部分正在做一些非常有意义的事情。
如果你过分依赖宏,你会遇到认知漂移的(组合名称)问题,你现在正在设计自己的语言(宏程序),但编译器和正在运行的程序正在使用另一种语言。简单的映射不会使新语言变得更加繁琐,但即使是简单的映射也会因为宏仅在文本替换级别上运行而变得非常复杂。
如果您使用的是C ++,那么更好的解决方案就是使用模板。模板提供了许多与宏相同的功能,除了它们不会受到认知漂移的影响,因为模板会替代类型系统的意识。
随着C语言结构的语法和含义的演变,您会发现较新的语言经常尝试通过纯C解决方案“修复”重复代码所需的的问题。尝试学习一些“接近”C的新语言,您将对这种代码重复的减少方式有所了解,从而在C语言的“生成”工作中做出更好的选择。