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()and関数を作成できました。.Write(T value)Cからこの動作を取得する方法はありますか? void ポインターと vtables を組み合わせて使用​​する方法があると思われます。これをよりポリモーフィックな方法で処理し、各項目を NVRAM に読み書きする機能を同様の方法で呼び出したいと思います。

4

5 に答える 5

9

マクロを使用して、C で C++ テンプレートを [かなり厳密に] シミュレートできます。

これを行うには、少なくとも 2 つの方法があります。


最初の方法:「ゴム印」マクロ

関数のマクロの宣言/定義を定義する

#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_intWrite_Value_intRead_value_longおよびの宣言と定義を「生成」しWrite_value_longます。


2 番目の方法: パラメータ化されたインクルード ファイル

2 つのヘッダー ファイルを作成します。宣言用 ( read_write.h.template)

TYPE__ CONCAT(Read_Value_, SUFFIX__)(void);
void CONCAT(Write_Value_, SUFFIX__)(TYPE__ val);

および定義用の 1 つ ( 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 に答える