C言語マクロ定義のテクニック

8690 ワード

出典:http://blog.chinaunix.net/uid-14022540-id-2849095.html
 
1.マクロの中の「萼」と「菗33751;」の使い方
 
一、一般的な使い方
私たちはマクロパラメータを使って文字列に変えて、二つのマクロパラメータを一緒にくっつけます。 
#include <stdio.h>

#define CONS(a,b) ((int)(a##e##b))
#define STR(s) #s

int main()
{
    printf("%s
",STR(ABC)); printf("%d
",CONS(2,3)); return 0; } /* root@oucaijun:/work/dcc# gcc *.c; ./a.out ABC 2000 */
二、マクロパラメータが別のマクロの場合: 注意しなければならないのは、凡宏の定義において、「〓」や「〓〓」というところのマクロパラメータが展開されないことです。
1、'33852;'と'璢33751;'の場合ではなく、自然に展開されます。
萼デfine TOW      (2)
_defineMUL(a,b)(a*b)
 printf(「%d*%d=%d」、TOW、TOW、MUL(TOW、TOW);
この行のマクロは次のように展開されます。
printf('%d*%d=%d",(2),((2)*(2)))))));
MULのパラメータTOWは(2)に展開されます。 
 
2,「萼」または「菗菗」があるときは、「葃」または「\ӗ〹〹〹」のローカルマクロパラメータは再展開されません。
湖南省にある地名          (2)
〹define CONS(a,b) (int)(a〓〓〓〓〓〓〓〓〓〓〓〓〓〓))
printf("%s",CONS(A,A));               // comple error  
この行は:
printf(“%s”、int(AeA); 
 
しかし、この問題を解決する方法はとても簡単です。マクロの中間変換を多くします。
#include <stdio.h>

#define _GET_FILE_NAME(f) (#f)
#define GET_FILE_NAME(f) _GET_FILE_NAME(f)

int main()
{
    //   GET_FILE_NAME(f)   ,        #,            ,      
    static char FILENAME[] = GET_FILE_NAME(__FILE__);//"test.c"
    printf("%s
", FILENAME); // _GET_FILE_NAME(f) , __FILE__ // _GET_FILE_NAME , , , static char FILENAME2[] = _GET_FILE_NAME(__FILE__);//__FILE__ printf("%s
", FILENAME2); return 0; } /* root@oucaijun:/work/dcc# gcc *.c; ./a.out "test.c" __FILE__ */
 2.マクロトラッキングデバッグ
#include <stdio.h>
#include <time.h>

int main()
{
    time_t t;
    time(&t);
    
    printf("file:%s, line:%d, function:%s, msg:%s, date:%s
", \ __FILE__, __LINE__, __FUNCTION__,"hello", ctime(&t)); return 0; } /* root@oucaijun:/work/dcc# gcc *.c; ./a.out file:1.c, line:11, function:main, msg:hello, date:Tue Jul 21 17:03:01 2015 */
    _DEBUG,              

#include <stdio.h> #include <time.h> #define _DEBUG #ifdef _DEBUG #define DEBUGMSG(msg, date) \ do{\ printf("msg: %s; file:%s, line:%d, date:%s
",msg, __FILE__, __LINE__, date);\ }while(0) #else #define DEBUGMSG(msg,date) #endif int main() { time_t now; time(&now); DEBUGMSG("hello",ctime(&now)); return 0; } /* root@oucaijun:/work/dcc# gcc *.c; ./a.out msg: hello; file:1.c, line:22, date:Tue Jul 21 17:05:44 2015 */
 3.以下にソフトウェアでよく使われるマクロ定義を挙げます。
1,ヘッダファイルが重複して含まれることを防止する
ヽoo。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。H
ハデfine COMDEF_H
  //ヘッダファイルの内容
湖南省にある地名 
2,いくつかのタイプを再定義し、様々なプラットフォームとコンパイラの違いによるバイト数の違いを防止し、移植を容易にする。
typedef  unsigned char      book;     /* Boolean value type.*/
typedef  unsigned long int  uint 32;      /* Unisigned 32 bit value*/
typedef  unsigned shart     uint 16;      /* Unisigned 16 bit value*/
typedef  unsigned char      uint 8       /* Unisigned 8  bit value*/
typedef  signed long int    int 32;       /* Signed 32 bit value*/
typedef  signed shart       int 16       /* Signed 16 bit value*/
typedef  signed char        int 8;        /* Signed 8  bit value*/ 
 
typedef  unsigned char     byte;         /* Unisigned 8  bit value type.*/
typedef  unsigned shart    word;         /* Unisinged 16 bit value type.*/
typedef  unsigned long     dword;        /* Unisigned 32 bit value type.*/
 
3,指定されたアドレスのバイトまたはワードを取得します。
同前  MEMB(x)  (*(((byte*)(x))
同前  MEMW(x)  (*((word*)(x)) 
 
4,最大値と最小値を求める
   #define  MAX(x,y)((x)>(y))?(x):(y)
   #define  MIN(x,y)((x)<(y)))?(x):(y) 
 
7,LSB形式によって、二つのバイトをワードに変換する。
 #define  FLIPW(ray)(((((word)[0]*256)+(ray)[1]) 
 
8,LSB形式で一つのWordを二バイトに変換する
 #define  FLOW(ray,val)\
   (ray)[0]=(val)/256);\
   (ray)[1]=(val)&0 xFF) 
 
12、1文字を大文字に変換します。
 #define  UPCSE(c)(((((c)>='a'&(c)='0'&((c)='0'&((*)='A'&(c)='a'&((c)  (val)?(val)+1:(val) 
 
20、マクロ定義の使用防止はエラーです。
括弧で含める
do{}while(0)の文で複数の語句を含んでエラーを防止します。
 
eg:((zhi define ADD(a,b)do{a+b;)
                    a++;}while(0)