1

我在嵌入式微控制器中工作,我必须将多种类型的数据读/写到非易失性 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 指针和 vtables 的某种组合。我想以一种更加多态的方式处理这个问题,并具有以类似方式调用的将每个项目读/写到 NVRAM 的功能。

4

5 回答 5

9

您可以[非常接近地]使用宏在 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_longWrite_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++ 模板一起使用一样。

于 2012-07-09T15:18:31.003 回答
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));

最后,您可以以各种方式“模拟”模板。

于 2012-07-09T15:12:49.317 回答
3

根据目标类型返回不同的类型(几乎?)用 C 是不可能的。不过,你可以用宏来模仿它。例如:

#define WRITE(x)  write_value(x, sizeof(x))
#define READ(x)  read_value(&x, sizeof(x))

现在您可以编写 write_value() 和 read_value() 以根据长度复制数据,同时考虑内部例程中的字节序。

于 2012-07-09T15:13:54.930 回答
3

C 中没有这样的东西。但是,您可以使用 struct 方法。

#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指针。

于 2012-07-09T15:18:14.507 回答
2

查看 Posixreadwrite函数,然后执行类似的操作:

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));
于 2012-07-09T15:16:23.037 回答