我正在尝试用C编写一些库,我有这个联盟:
union { INTEGER, DOUBLE, FLOAT } Types;
typedef struct X {
Type type;
union { double a, float b, int c; } val;
struct X *next;
} MyStruct;
我想要插入功能。例如,它可以是一些结构的插入函数,如树,优先级队列或其他:
insertInt(..., int y), insertFloat(..., float y), insertDouble(..., double y).
通过这种方式,我有很多冗余代码,这是不可取的。另一方面,我们在atoi
中有标准字符串转换函数atol
,atof
,<stdlib.h>
,并且开发库,更好的是重复代码或以某种方式执行它可能与指向void的指针并识别带有类型的类型(在本例中)?
insertInt示例:
MyStruct* insertInt(MyStruct *root, int val) {
MyStruct *newNode = (MyStruct*)malloc(sizeof(MyStruct));
newNode->next = root;
newNode->val.c = val;
newNode->type = INTEGER;
return newNode;
}
答案 0 :(得分:1)
您可以使用宏模板来避免源代码重复:
MAKE_INSERT_FUNC(insertDouble, double, a);
MAKE_INSERT_FUNC(insertFloat, float, b);
MAKE_INSERT_FUNC(insertInt, int, c);
以这种方式实例化函数:
MyStruct *insertDouble(MyStruct **root, double val);
MyStruct *insertFloat(MyStruct **root, float val);
MyStruct *insertInt(MyStruct **root, int val);
您仍然需要在头文件中编写声明:
insertXXX()
我更改了API:root
函数获取指向列表root
指针的指针,因此您无需将返回值存储回原始指针,您可以测试分配是否失败没有破坏现有的清单。
请注意,重复代码(在这种情况下具有较小的变体)比重复源(在进行修改和修复错误时往往变得不一致)要小得多。例如,您可以修改模板以附加新节点,而不是将其添加到ADMINS = (
('Me', 'me@me.com'),
)
MANAGERS = ADMINS
DEBUG = False
ALLOWED_HOSTS = ['*']
,并且所有insertXXX函数都将获得新行为。
答案 1 :(得分:0)
这可行吗
#include <stdio.h>
#include <stdlib.h>
enum Type
{
Integer = sizeof("int"),
DoublePrecision = sizeof("double"),
SinglePrecision = sizeof("float")
};
struct GenericNode
{
enum Type type;
union
{
int _int;
double _double;
float _float;
} value;
struct GenericNode *left;
struct GenericNode *right;
};
#define DEFINE_GENERIC_NODE_API_FOR(__type) \
struct GenericNode *generic_node_create_ ## __type ## _node(__type value) \
{ \
struct GenericNode *element; \
element = malloc(sizeof(*element)); \
if (element == NULL) \
return NULL; \
element->left = NULL; \
element->right = NULL; \
element->type = sizeof(#__type); \
switch (element->type) \
{ \
case Integer: \
element->value._int = value; \
break; \
case DoublePrecision: \
element->value._double = value; \
break; \
case SinglePrecision: \
element->value._float = value; \
break; \
} \
return element; \
} \
\
__type generic_node_get_value_as_ ## __type(struct GenericNode *node) \
{ \
switch (node->type) \
{ \
case Integer: \
return node->value._int; \
case DoublePrecision: \
return node->value._double; \
case SinglePrecision: \
return node->value._float; \
} \
return (__type) 0; \
}
DEFINE_GENERIC_NODE_API_FOR(int)
DEFINE_GENERIC_NODE_API_FOR(double)
DEFINE_GENERIC_NODE_API_FOR(float)
int
main(void)
{
struct GenericNode *node;
int value;
node = generic_node_create_int_node(5);
if (node == NULL)
return -1;
value = generic_node_get_value_as_int(node);
fprintf(stdout, "%d\n", value);
return 0;
}
这是一个 API 工厂,int
有三个字符且double
有6和float
5这一事实用于创建枚举(<你可以添加char
)和无符号版本。这样可以正常工作,因为它显然是你所需要的,我认为它可能有用。
请注意,您可以根据类型选择 get_value 函数,但是您必须适当地声明目标变量。