我正在使用嵌入式微控制器,我必须将多种类型的数据读/写到非易失性RAM(NVRAM)。我想避免为每个值编写单独的读/写函数来存储在NVRAM中,如下所示:
void Write_Value1(int value);
int Read_Value1(void);
void Write_Value2(unsigned long value);
unsigned long Read_Value2(void);
...
随着读/写项目列表的增长,维护起来非常麻烦。有几种方法可以用C ++解决这个问题,例如模板。使用模板,我可以编写一个.Read()
和.Write(T value)
函数,每个要读/写的项都可以访问。无论如何从C获得这种行为?我怀疑有一些方法,使用void指针和vtable的一些组合。我想以更多态的方式处理这个问题,并且具有以类似的方式读取/写入每个项目到NVRAM的功能。
答案 0 :(得分:10)
您可以[非常接近]使用宏来模拟C中的C ++模板。
至少有两种方法可以做到这一点。
第一种方法:“橡皮图章”宏
为函数定义声明/定义宏
#define DECLARE_READ_WRITE(suffix, type)\
type Read_Value_##suffix(void);
void Write_Value_##suffix(type val);
#define DEFINE_READ_WRITE(suffix, type)\
type Read_Value_##suffix(void) {\
/* your code */ \
}\
void Write_Value_##suffix(type val) {\
/* your code */ \
}
然后在一些头文件中执行
DECLARE_READ_WRITE(long, long)
DECLARE_READ_WRITE(int, int)
并在某些实施文件中
DEFINE_READ_WRITE(long, long)
DEFINE_READ_WRITE(int, int)
将“生成”Read_Value_int
,Write_Value_int
,Read_value_long
和Write_value_long
的声明和定义。
第二种方法:参数化包含文件
创建两个头文件。一个用于声明(read_write.h.template
)
TYPE__ CONCAT(Read_Value_, SUFFIX__)(void);
void CONCAT(Write_Value_, SUFFIX__)(TYPE__ val);
和一个用于定义(read_write.c.template
)
TYPE__ CONCAT(Read_Value_, SUFFIX__)(void)
{
/* your code */
}
void CONCAT(Write_Value_, SUFFIX__)(TYPE__ val)
{
/* your code */
}
这里CONCAT
是宏标记连接的通常实现(也可以/应该在第一种方法中使用)。
然后将“模板化”代码包含在适当的头文件和实现文件中
#define TYPE__ int
#define SUFFIX__ int
#include "read_write.h.template"
#undef TYPE__
#undef SUFFIX__
#define TYPE__ long
#define SUFFIX__ long
#include "read_write.h.template"
#undef TYPE__
#undef SUFFIX__
在带有read_write.c.template
标题的某个实现文件中也是如此。
后一种方法具有产生可调试代码的额外好处。即您可以在调试器中单步执行它,就像它通常适用于C ++模板一样。
答案 1 :(得分:4)
你可以使用void指针和大小来做到这一点:
void write_value (void *data, size_t size);
void* read_value (size_t size);
然后:
write_value ( (void *) &int_val, sizeof (int));
write_value ( (void *) &ulong_val, sizeof (unsigned long));
intptr = read_value (sizeof (int));
charptr = read_value (sizeof (char));
read_value
然后需要malloc
某些东西并将其返回。当你宁愿读自动时,这有时可能只是开销。然后做:
/* Declaration. */
void read_value (void *data, size_t size);
/* Use. */
read_value (&automatic_var, sizeof (automatic_var));
最后,您可以在all sorts of ways中“模拟”模板。
答案 2 :(得分:3)
基于目标类型返回一个不同的类型(几乎?)不可能用C.你可以用宏来模仿它。例如:
#define WRITE(x) write_value(x, sizeof(x))
#define READ(x) read_value(&x, sizeof(x))
现在你可以编写write_value()和read_value()来根据长度复制数据,同时考虑内部例程中的字节顺序。
答案 3 :(得分:3)
C中没有这样的东西。但是,你可以使用结构方法。
#define T_VOID 0
#define T_INT 1
#define T_ULINT 2
typedef struct
{
int type;
union
{
int a;
unsigned long b;
} my_union;
} my_struct;
void write_value(my_struct *s)
{
switch (s->type)
{
case T_VOID:
// do something
break;
case T_INT:
// do something with s->my_union.a
break;
case T_ULINT:
// do something with s->my_union.b
break;
}
}
以同样的方式,read_value
将返回my_struct
指针。
答案 4 :(得分:2)
查看Posix read
和write
函数,然后执行类似操作:
void read(int address, void * data, int size);
void write(int address, const void * data, int size);
然后:
read(address, &x, sizeof(x));
write(address, &x, sizeof(x));