11

これを行うためのより良い非マクロの方法があることを無視して(悲しいことに、私には正当な理由があります)、マクロを使用して大量のジェネリックコードを書く必要があります。基本的に、いくつかの事前に指定されたタイプに対して多数の関数を生成するマクロライブラリ。

多数の既存の単体テストを壊さないようにするために、ライブラリが実行する必要があることの1つは、すべてのタイプについて、印刷用にすべての大文字でそのタイプの名前を生成することです。たとえば、タイプ「フラグ」は「FLAG」として印刷する必要があります。

タイプごとに定数を手動で書き出すことができます。

#define flag_ALLCAPSNAME FLAG

しかし、これは理想的ではありません。これをプログラムで実行できるようにしたいと思います。

現在、私はこれを一緒にハックしました:

char capname_buf[BUFSIZ];
#define __MACRO_TO_UPPERCASE(arg) strcpy(capname_buf, arg); \
 for(char *c=capname_buf;*c;c++)*c = (*c >= 'a' && *c <= 'z')? *c - 'a' + 'A': *c;
__MACRO_TO_UPPERCASE(#flag)

これは私がある程度やりたいことをします(つまり、このコードの後に​​、capname_bufはその内容として「FLAG」を持ちます)が、代わりにマクロを使用して文字列リテラルを定義できるソリューションを好みます。これは必要ありません。愚かなバッファ。

これを行う方法がわかりませんが、おそらく何か明らかなものが欠けていますか?

可変個引数のforeachループマクロを(このように)記述していますが、#flagによって生成された文字列リテラルの内容を変更することはできません。いずれの場合も、ループマクロを反復処理するには文字ポインターのリストが必要です(つまり、インデックスなどではなく、リストを繰り返し処理します)。

考え?

4

2 に答える 2

15

ポータブルC99では、定数文字列をすべて大文字に変換するマクロを使用することはできません(特に、文字の概念は文字エンコードに関連しているためです。UTF8文字はASCII文字と同じではありません)。

ただし、他の解決策を検討することもできます。

  • それを行うためにエディタをカスタマイズします。たとえば、必要に応じて各Cソースファイルを更新するemacsコードを記述できます。

  • #defineCソースコードでプリプロセッサを使用します(おそらく、いくつかの#include-dファイルで大量のプリプロセッサを出力する単純なCコードジェネレータスクリプト)。

  • GCC拡張機能を使用して

    #define TO_UPPERCASE_COUNTED(Str,Cnt)
    #define TO_UPPERCASE(Str) TO_UPPERCASE_COUNTED(Str,__COUNT__) {( \
       static char buf_##Cnt[sizeof(Str)+4]; \
       char *str_##Cnt = Str; \
       int ix_##Cnt = 0; \
       for (; *str_##Cnt; str_##Cnt++, ix_##Cnt++) \
         if (ix_##Cnt < sizeof(buf_##Cnt)-1) \
             buf_##Cnt[ix_##Cnt] = toupper(*str_##Cnt); \
       buf_##Cnt; )}
    
  • おそらくMELT(GCCを拡張するためのドメイン固有言語)を使用してGCCをカスタマイズ__builtin_capitalize_constantし、ジョブを実行できるようにします(編集:MELTは非アクティブなプロジェクトになりました)。または、それを実行する独自のGCCプラグインをC ++でコーディングします(注意、特定のGCCバージョンでのみ機能します)。

于 2012-09-17T08:43:51.710 に答える
1

cプリプロセッサを使用してこれを完全に行うことはできません。これは、プリプロセッサが入力を(アトミック)として読み取り、pp-tokensそこから出力を構成するためです。プリプロセッサがpp-tokenを個々の文字に分解するための構造はありません(とにかくここであなたを助ける人は誰もいません)。

あなたの例では、プリプロセッサが文字列リテラルを読み取るとき、"flag"それは基本的にテキストのアトミックチャンクです。そのようなチャンクを条件付きで削除したり、それらをより大きなチャンクに接着したりするための構造があります。

ある意味でaを分解できる唯一の構成pp-tokenは、いくつかの式を使用することです。ただし、これらの式は算術型でのみ機能するため、ここでは役に立ちません。

あなたのアプローチは、C言語構造を使用することによってこの問題を回避します。つまり、実行時に変換を行います。プリプロセッサが行う唯一のことは、文字列を変換するためにCコードを挿入することです。

于 2016-04-05T11:29:21.300 に答える