マクロ定義マクロパラメータ

4509 ワード

パラメータ付きマクロ定義、マクロパラメータを使用した文字列(#演算子)の作成
次の2つのマクロ定義を見てみましょう.
#define PSQR(x) printf("The square of x is %d.
",(x)*(x)) #define PSQR(x) printf("The square of "#x" is %d.
",(x)*(x))

私たちの目標はマクロを使用するときにマクロボディのxをマクロパラメータに置き換えることですが、最初のマクロ定義はこのような目標を達成することはできません.引用符のxは普通のテキストと見なされ、置き換えられないからです.このような機能を実現するには、#演算子を使用します.
 
PSQR(x)の2つの異なるマクロ定義出力の結果は以下の通りである.
The square of x is 4.
The square of 2 is 4.
defineマクロ定義の#,#,@#,記号
出所不明、seclu整理1、#(stringizing)文字列化オペレータです.マクロ定義の入力パラメータ名を、パラメータ名文字列を二重引用符で囲むように変換します.入力パラメータのあるマクロ定義でのみ使用でき、マクロ定義体に配置する必要があるパラメータ名です.たとえば、#define example(instr)printf(「the input string is:t%s」、#instr)#define example 1(instr)#instrマクロ定義を使用する場合:example(abc);コンパイル時にはprintf(「the input string is:t%s」,「abc」);string str=example1(abc); string str="abc";注意:スペースの処理a.入力パラメータ名の前後のスペースは無視されます.例えばstr=example 1(abc);str=「abc」に拡張されます.b.入力パラメータ名の間にスペースがある場合、コンパイラは各サブ文字列を自動的に接続し、各サブ文字列のうち1つだけスペースで接続し、残りの1つのスペースを無視します.例えばstr=exapme(abc def);str=「abc def」に拡張されます.2、##(token-pasting)シンボル接続オペレータマクロ定義:パラメータ名、すなわちdefine sum(a,b)(a+b)などのパラメータ名;のaとbはいずれもあるパラメータの代表記号、すなわち形式パラメータである.##の役割は、マクロ定義の複数のシェイプを実際のパラメータ名にパラメータ化することです.例:#define exampleNum(n)num##n int num 9=9;使用:int num=exampleNum(9);int num=num 9に拡張されます.注意:1.パラメータを##で接続する場合、##前後のスペースは有無を指定できます.例えば、#define exampleNum(n)num##nは、#define exampleNum(n)num##n 2に相当する.接続後の実際のパラメータ名は、実際に存在するパラメータ名またはコンパイラで既知のマクロ定義//preprocessor_token_pasting.cpp    #include     #define paster( n ) printf_s( "token"#n "= %d", token##n )    int token9 = 9;     int main()     {        paster(9);}実行結果:token 9=9また、##後のパラメータ自体もマクロであれば、##はこのマクロの展開を阻止します.  #define STRCPY(a, b)    strcpy(a ## _p, #b)  int main()   {       char var1_p[20];       char var2_p[30];       strcpy(var1_p, "aaaa");       strcpy(var2_p, "bbbb");       STRCPY(var1, var2);       STRCPY(var2, var1);       printf("var1 = %s", var1_p);       printf("var2 = %s", var2_p);       return 0;             STRCPY(STRCPY(var1,var2),var2);}3、@#(charizing)文字化オペレータ.入力パラメータのあるマクロ定義にのみ使用でき、マクロ定義体に配置する必要があるパラメータ名.伝達された単一文字パラメータ名を文字に変換し、一対の単一参照で囲む役割を果たす.#define makechar(x)#@xa=makechar(b);展開すると、a='b';4、行続行オペレータ定義マクロが1行で完全に表現されない場合、次の行がこのマクロの定義を続行することを「」で表すことができます.
その他:その他のネットユーザーについて##と#の補充1.簡単に言えば、「###」は接続を区切る方法で、先に区切ってから強制的に接続する役割を果たします.ここで、区切りの役割はスペースに似ています.通常のマクロ定義では,プリプロセッサは一般にスペースを成分セグメントフラグに解釈し,各セグメントを前と比較すると同じものが置き換えられることを知っている.しかし、この結果、置換されたセグメントの間にいくつかのスペースが存在する.これらのスペースを表示したくない場合は、スペースの代わりに###を追加できます.他の区切りフラグには、+、-、*、/、[,]、...、などのオペレータが含まれています.したがって、次のマクロ定義にはスペースはありませんが、define add(a,b)a+bという意味のある定義を表し、その強制接続の役割は、前の文字列との間のスペースを削除し、両者を接続することです. 2. 列挙--以下のマクロ定義の違いを比較してみます#define A 1(name,type)type name_##type##_type//または#define A 2(name,type)type name#####type##_type   A1(a1, int);     A2(a1, int); 説明:1)最初のマクロ定義では、「name」と最初の「_」間、および2番目の""2番目のtypeとの間には区切られていないので、プリプロセッサはname_##をtype##_typeは「name_」、「type」、および「_type」は、中間に「type」だけがマクロの前に現れるので、マクロに置き換えることができます.2)2番目のマクロ定義では、「name」と1番目の「_」間も区切られているので、プリプロセッサはname#####をtype##_typeは「name」「_」の4つのセグメントに解釈されます.「type」および「_type」は、その間にマクロに置き換えられる2つがある.3)A 1およびA 2の定義は、#define A 1(name,type)type name_ ##type ##_type         //         #define A2(name, type)  type name ##_ ##type ##_typeの結果、##は前のスペースを削除して強い接続を完了し、上の結果と同じマクロ定義を得る.その他の関連--単独の#と単独の#は、この変数を置換した後、二重引用符を付けて引き起こすことを示します.例えば#define_stringify_1(x)#xでは_stringify_1(linux)<==>「linux」だから、MODULE_DEVICE_TABLE    #define MODULE_DEVICE_TABLE(type,name)        MODULE_GENERIC_TABLE(type##_device,name)     #define MODULE_GENERIC_TABLE(gtype,name)        extern const struct gtype##_id __mod_##gtype##_table        __attribute__ ((unused,alias(_stringify(name))得られたMODULE_DEVICE_TABLE(usb, products)                                <==> MODULE_GENERIC_TABLE(usb_device,products)    <==> extern const struct usb_device_id __mod_usb_device_table             __attribute__ ((unused,alias(「products」)alias attributeには二重引用符が必要であることに気づき、ここでは_stringify(name)はnameに二重引用符を付ける.また、外部変数「_mod_usb_device_table」が、本駆動専用のユーザによってカスタマイズされた変数productsにaliasされていることにも注目する.この外部変数がどのように使用されているかは、「probe()プロセス分析」を参照してください.4.分析方法と検証方式--簡単なCプログラムを作成してマクロで変数を定義し、同時に直接方式で同じ変数を定義し、レポートをコンパイルして繰り返し定義する.マクロで変数を定義し、そのマクロで定義した変数名を直接使用し、コンパイルが通過し、実行結果が正しい.printfを使用して文字列データを印刷します.printf("token macro is %s", __stringify_1(a1));