1

オフセットの自動生成に役立つマクロを定義したいと思います。このようなもの:

#define MEM_OFFSET(name, size) ...

MEM_OFFSET(param1, 1);
MEM_OFFSET(param2, 2);
MEM_OFFSET(param3, 4);
MEM_OFFSET(param4, 1);

次のコードを生成する必要があります。

const int param1_offset = 0;
const int param2_offset = 1;
const int param3_offset = 3;
const int param4_offset = 7;

また

enum {
  param1_offset = 0,
  param2_offset = 1,
  param3_offset = 3,
  param4_offset = 7,
}

または(Cプリプロセッサを確実に使用することはできませんが、誰が知っているか;)

#define param1_offset 0
#define param2_offset 1
#define param3_offset 3
#define param4_offset 7

外部のawk/bash / ...スクリプトを実行せずに実行することは可能ですか?

KeilC51を使用しています

4

5 に答える 5

4

enumで解決策を見つけたようです:

#define MEM_OFFSET(name, size) \
    name ## _offset, \
    ___tmp__ ## name = name ## _offset + size - 1, // allocate right bound offset and introduce a gap to force compiler to use next available offset

enum {
 MEM_OFFSET(param1, 1)
 MEM_OFFSET(param2, 2)
 MEM_OFFSET(param3, 4)
 MEM_OFFSET(param4, 1)
};
于 2013-01-15T23:44:59.967 に答える
2

投稿へのコメントで、EEPROMメモリマップを管理していると述べているため、この回答は、特定の質問に回答するのではなく、メモリオフセットの管理に関連しています。

EEPROMメモリを管理する1つの方法は、パック構造体を使用することです。つまり、各要素の間にスペースがないものです。構造体はインスタンス化されることはなく、オフセット計算にのみ使用されます。

typedef struct {
    uint8_t param1;
#ifdef FEATURE_ENABLED
    uint16_t param2;
#endif
    uint8_t param3;
} __packed eeprom_memory_layout_t;

次に、次のようなコードを使用して、必要に応じて(テストされていない)各要素のオフセットを決定できます。これは、offsetofstddefマクロを使用します。

uint16_t read_param3(void) {
    uint8_t buf;
    eeprom_memory_layout_t * ee;

    /* eeprom_read(offset, size, buf) */
    eeprom_read(offsetof(eeprom_memory_layout_t, param3), sizeof(ee->param3), &buf);

    return buf;
}

構造体がインスタンス化されることはないことに注意してください。このような構造体を使用すると、メモリマップが一目でわかりやすくなり、マクロを使用して、アクセス中offsetofおよびsizeofアクセス中の呼び出しを簡単に抽象化できます。

于 2013-01-16T00:04:00.030 に答える
0

いくつかのプリプロセッサ宣言に基づいていくつかの構造を作成したい場合は、次のようにすることができます。

#define OFFSET_FOREACH(MODIFIER)    \
    MODIFIER(1)                     \
    MODIFIER(2)                     \
    MODIFIER(3)                     \
    MODIFIER(4)

#define OFFSET_MODIFIER_ENUM(NUM) param##NUM##_offset,
enum 
{
    OFFSET_FOREACH(OFFSET_MODIFIER_ENUM)
};

プリプロセッサは、次のコードを生成します。

enum
{
    param1_offset,
    param2_offset,
    param3_offset,
    param4_offset,
}

誰かが前任者の合計でオフセット値を計算するための素晴らしいプリプロセッサのトリックを理解すると確信しています:)

于 2013-01-15T23:31:58.120 に答える
0

これをCコードで行う場合、宣言はCで定数const intを宣言しないことに注意する必要があります。名前付き定数を宣言するには、またはのいずれかを使用する必要があります。enum#define

int特に定数が必要な場合enumはうまくいきますが、自動生成の部分はとにかくトリッキーかもしれません。頭のてっぺんから、私は醜いものしか思いつかない

#define MEM_OFFSET_BEGIN(name, size)\
  enum {\
    name##_OFFSET = 0,\
    name##_SIZE__ = size,

#define MEM_OFFSET(name, size, prev_name)\
  name##_OFFSET = prev_name##_OFFSET + prev_name##_SIZE__,\
  name##_SIZE__ = size,

#define MEM_OFFSET_END()\
  };

その後

MEM_OFFSET_BEGIN(param1, 1)
MEM_OFFSET(param2, 2, param1)
MEM_OFFSET(param3, 4, param2)
MEM_OFFSET(param4, 1, param3)
MEM_OFFSET_END()

言うまでもなく、前のオフセット宣言を名前で参照するために次のオフセット宣言が必要であるという事実は、この構成の目的のほとんどを無効にします。

于 2013-01-15T23:35:07.413 に答える
0

次のようなものを試してください:

#define OFFSET(x) offsetof(struct {\
char param1[1], param2[2], param3[4], param4[1];\
},x)

次に、などを使用できますOFFSET(param1)。これは整数定数式でもあります。

于 2013-01-16T03:49:17.293 に答える