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/... 脚本?

我正在使用 Keil C51

4

5 回答 5

4

看来我找到了枚举的解决方案:

#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 存储器的一种方法是使用打包结构。即,每个元素之间没有空间。该结构从未实例化,它仅用于偏移计算。

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

然后,您可以根据需要使用如下代码来确定每个元素的偏移量(未经测试)。这使用了stddef 宏的offsetof 。

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;
}

请注意,该结构永远不会被实例化。使用这样的结构可以很容易地一目了然地看到你的内存映射,并且可以很容易地使用宏来抽象出对访问offsetofsizeof访问期间的调用。

于 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

尝试类似:

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

然后你可以使用OFFSET(param1),等等,它甚至是一个整数常量表达式。

于 2013-01-16T03:49:17.293 回答
0

如果您在 C 代码中执行此操作,则必须记住const int声明不会在 C 中声明常量。要声明命名常量,您必须使用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 回答