1

UI テキストを 1 つの配列に簡単に格納できるプリプロセッサ定義がいくつかあります (以下を参照)。また、他の言語のサポートも煩雑になりません。

#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 を占有します。プログラム内の 2 つの大きな文字列テーブルが、使用可能な RAM の約 30% を占めています。したがって、これは無視できません。

enum 値が、コード空間に格納された 1 つの大きな 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 プリプロセッサを使用する賢い方法はありますか? 列挙型を手動で作成したり、配列を変換するビルド前のコマンド プログラムを作成したりする必要はありません。

4

4 に答える 4

2

ポインターの配列をconstほとんど (すべて?) にすると、ツール チェーンはその配列を ROM/フラッシュに配置します。これは通常、スペースの問題が少なくなります。

static const char* const name##_sztable[] = /* ... */
//                 ^^^^^
于 2012-10-09T19:49:47.073 に答える
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
于 2012-10-09T17:51:44.320 に答える
0

してみませんか:

#if ENGLISH
#define STR_ONE "one"
#define STR_TWO "two"
...
#elif SPANISH
#define STR_ONE "uno"
#define STR_TWO "dos"
...
#endif

文字列ポインタ自体ではなく、オフセットが必要な理由はありますか?

于 2012-10-09T18:18:39.720 に答える
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 などのマクロ メタ パッケージを使用すると、すべてがより簡単になります。

于 2012-10-09T18:07:48.373 に答える