我有一些预处理器定义,可以在单个数组中轻松存储UI文本(见下文)。也使得支持其他语言不那么麻烦。
#define DECLARE_STRING_ENUM_FST(name, value) name
#define DECLARE_STRING_ENUM_SND(name, value) value
#define DECLARE_STRING_ENUM(name, macro) \
typedef enum name { macro(DECLARE_STRING_ENUM_FST) } name; \
static const char* name##_sztable[] = { macro(DECLARE_STRING_ENUM_SND) }; \
// this is a string table usage
#define MSG_ENUM_(X) \
X(STR_ONE, "One"), \
X(STR_TWO, "Two"), \
X(STR_THREE, "Three"), \
X(STR_PRESS_ENTER, "Press Enter")
// the actual declaration is here
DECLARE_STRING_ENUM(menu, MSG_ENUM_)
结果是一个字符串数组和一个表示数组中索引的枚举。
然而,因为它是一个指向常量char *的指针数组,所以它占用ram,这在这个设备上是非常稀缺的。程序中的几个大字符串表占用了大约30%的可用RAM。所以这不容忽视。
如果枚举值是存储在代码空间中的一个大的const char字符串中的以null结尾的子字符串的起始位置,则RAM的依赖性将变为零。
即:
menu_sztable[] = "One\0Two\0Three\0Press Enter\0";
STR_ONE -> 0
STR_TWO -> 4
STR_Three -> 8
STR_PressEnter -> 14
有没有一种聪明的方法来使用C-Preprocessor来实现这一目标?我想避免手动构建枚举或者必须编写转换数组的预构建命令程序。
答案 0 :(得分:1)
这不是一个完整的解决方案,也许是中途......
#include <stdlib.h>
#include <stddef.h>
static struct foo {
char arr0[5];
char arr1[4];
char arr2[4];
} tmp = { "Zero","One","Two"};
enum {
ARR0 = offsetof(struct foo, arr0),
ARR1 = offsetof(struct foo, arr1),
ARR2 = offsetof(struct foo, arr2)
};
int main()
{
printf("%d %d %d\n",ARR0,ARR1,ARR2);
return 0;
}
无法记住链接器选项,但在拆解时,我会得到:
.file "tst.c"
.data // manually replace with .text
_tmp:
.ascii "Zero\0"
.ascii "One\0"
.ascii "Two\0" // manually insert .data here, recompile and run...
.def ___main; .scl 2; .type 32; .endef
答案 1 :(得分:1)
如果您制作指针数组const
大多数(全部?)工具链会将该数组放入ROM / flash中,这通常对空间有较小的问题:
static const char* const name##_sztable[] = /* ... */
// ^^^^^
答案 2 :(得分:0)
你可以先定义一大堆编译时常量来保存你的字符串的位置,比如
#define DEFINE_LENGTH(NAME, STR) NAME ## _POS, \
NAME ## _DUMMY = (NAME ## _POS + sizeof(STR))
在枚举声明中
enum {
... your macro expansion goes here ...
};
然后通过连接
创建一个长字符串#define DEFINE_COMPONENT(NAME, STR) STR "\0"
在长字符串
的初始化内部char const table[] = ... your macro expansion goes here ...;
现在你的字符串指针是用
获得的#define DEFINE_VARIABLE(NAME, STR) *const NAME = &table[NAME ## _POS]
在以下设置中:
char const ... your macro expansion goes here ...;
(也许这里和那里仍然存在一些语法错误,但我希望你能得到它。)
如果您使用宏元数据包(例如boost或P99),那么所有这些都会更简单。
答案 3 :(得分:0)
为什么不这样做:
#if ENGLISH
#define STR_ONE "one"
#define STR_TWO "two"
...
#elif SPANISH
#define STR_ONE "uno"
#define STR_TWO "dos"
...
#endif
您是否有理由需要偏移而不是字符串指针?