青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

colorful

zc qq:1337220912

 

c++ 宏

c/c++ 宏中"#"和"##"的用法
2007年05月14日 星期一 上午 10:19
一、一般用法
我們使用#把宏參數變為一個字符串,用##把兩個宏參數貼合在一起.
用法:
#i nclude<cstdio>
#i nclude<climits>
using namespace std;
#define STR(s)      #s
#define CONS(a,b)   int(a##e##b)

int main()
{
     printf(STR(vck));            // 輸出字符串"vck"
     printf("%d\n", CONS(2,3));   // 2e3 輸出:2000
     return 0;
}

二、當宏參數是另一個宏的時候
需要注意的是凡宏定義里有用'#'或'##'的地方宏參數是不會再展開.

1, 非'#'和'##'的情況
#define TOW       (2)
#define MUL(a,b) (a*b)

printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));
這行的宏會被展開為:
printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
MUL里的參數TOW會被展開為(2).

2, 當有'#'或'##'的時候
#define A           (2)
#define STR(s)      #s
#define CONS(a,b)   int(a##e##b)

printf("int max: %s\n",   STR(INT_MAX));     // INT_MAX #i nclude<climits>
這行會被展開為:
printf("int max: %s\n", "INT_MAX");

printf("%s\n", CONS(A, A));                // compile error
這一行則是:
printf("%s\n", int(AeA));

INT_MAX和A都不會再被展開, 然而解決這個問題的方法很簡單. 加多一層中間轉換宏.
加這層宏的用意是把所有宏的參數在這層里全部展開, 那么在轉換宏里的那一個宏(_STR)就能得到正確的宏參數.

#define A            (2)
#define _STR(s)      #s
#define STR(s)       _STR(s)           // 轉換宏
#define _CONS(a,b)   int(a##e##b)
#define CONS(a,b)    _CONS(a,b)        // 轉換宏

printf("int max: %s\n", STR(INT_MAX));           // INT_MAX,int型的最大值,為一個變量 #i nclude<climits>
輸出為: int max: 0x7fffffff
STR(INT_MAX) -->   _STR(0x7fffffff) 然后再轉換成字符串;

printf("%d\n", CONS(A, A));
輸出為:200
CONS(A, A)   -->   _CONS((2), (2))   --> int((2)e(2))

三、'#'和'##'的一些應用特例
1、合并匿名變量名
#define   ___ANONYMOUS1(type, var, line)   type   var##line
#define   __ANONYMOUS0(type, line)   ___ANONYMOUS1(type, _anonymous, line)
#define   ANONYMOUS(type)   __ANONYMOUS0(type, __LINE__)
例:ANONYMOUS(static int);   即: static int _anonymous70;   70表示該行行號;
第一層:ANONYMOUS(static int);   -->   __ANONYMOUS0(static int, __LINE__);
第二層:                         -->   ___ANONYMOUS1(static int, _anonymous, 70);
第三層:                         -->   static int   _anonymous70;
即每次只能解開當前層的宏,所以__LINE__在第二層才能被解開;

2、填充結構
#define   FILL(a)    {a, #a}

enum IDD{OPEN, CLOSE};
typedef struct MSG{
   IDD id;
   const char * msg;
}MSG;

MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
相當于:
MSG _msg[] = {{OPEN, "OPEN"},
               {CLOSE, "CLOSE"}};

3、記錄文件名
#define   _GET_FILE_NAME(f)    #f
#define   GET_FILE_NAME(f)     _GET_FILE_NAME(f)
static char   FILE_NAME[] = GET_FILE_NAME(__FILE__);

4、得到一個數值類型所對應的字符串緩沖大小
#define   _TYPE_BUF_SIZE(type)   sizeof #type
#define   TYPE_BUF_SIZE(type)    _TYPE_BUF_SIZE(type)
char   buf[TYPE_BUF_SIZE(INT_MAX)];
      -->   char   buf[_TYPE_BUF_SIZE(0x7fffffff)];
      -->   char   buf[sizeof "0x7fffffff"];
這里相當于:
char   buf[11];

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

c和c++調式 利用宏獲得函數名
僅僅為了獲取函數名,就在函數體中嵌入硬編碼的字符串,這種方法單調乏味還易導致錯誤,不如看一下怎樣使用新的C99特性,在程序運行時獲取函數名吧。
   對象反射庫、調試工具及代碼分析器,經常會需要在運行時訪問函數的名稱,直到不久前,唯一能完成此 項任務并且可移植的方法,是手工在函數體內嵌入一個帶有該函數名的硬編碼字符串,不必說,這種方法非常單調無奇,并且輕易導致錯誤。本文將要演示怎樣使用 新的C99特性,在運行時獲取函數名。
  那么怎樣以編程的方式從當前運行的函數中得到函數名呢?
  答案是:使用__FUNCTION__ 及相關宏。
  引出問題
  通常,在調試中最讓人心煩的階段,是不斷地檢查是否已調用了特定的函數。對此問題的解決方法,一般是添加一個cout或printf()——假如你使用C語言,如下所示:
void myfunc()
{
cout<<"myfunc()"<<endl;
//其他代碼
}
通常在一個典型的工程中,會包含有數千個函數,要在每個函數中都加入一條這樣的輸出語句,無疑難過上“蜀山”啊,因此,需要有一種機制,可以自動地完成這項操作。
  獲取函數名
  作為一個C++程序員,可能經常碰到 __TIME__、__FILE__、__DATE__ ,__LINE__ 這樣的宏,它們會在編譯時,分別轉換為包含編譯時間、處理的轉換單元名稱及當前時間的字符串。
   在最新的ISO C標準中,如大家所知的C99,加入了另一個有用的、類似宏的表達式__func__,其會報告未修飾過的(也就是未裁剪過的)、正在被訪問的函數名。請 注重,__func__不是一個宏,因為預處理器對此函數一無所知;相反,它是作為一個隱式聲明的常量字符數組實現的:
static const char __func__[] = "function-name";
在function-name處,為實際的函數名。為激活此特性,某些編譯器需要使用特定的編譯標志,請查看相應的編譯器文檔,以獲取具體的資料。
  有了它,我們可免去大多數通過手工修改,來顯示函數名的苦差事,以上的例子可如下所示進行重寫:
void myfunc()
{
cout<<"__FUNCTION__"<<endl;
}
官 方C99標準為此目的定義的__func__標識符,確實值得大家關注,然而,ISO C++卻不完全支持所有的C99擴展,因此,大多數的編譯器提供商都使用 __FUNCTION__ 取而代之,而 __FUNCTION__ 通常是一個定義為 __func__ 的宏,之所以使用這個名字,是因為它已受到了大多數的廣泛支持。
  在Visual Studio 2005中,默認情況下,此特性是激活的,但不能與/EP和/P編譯選項同時使用。請注重在IDE環境中,不能識別__func__ ,而要用__FUNCTION__ 代替。
  Comeau的用戶也應使用 __FUNCTION__ ,而不是 __func__ 。
  C++ BuilderX的用戶則應使用稍稍不同的名字:__FUNC__ 。
  GCC 3.0及更高的版本同時支持 __func__ 和__FUNCTION__ 。
  一旦可自動獲取當前函數名,你可以定義一個如下所示顯示任何函數名的函數:
void show_name(const char * name)
{
cout<<name<<endl;
}
void myfunc()
{
show_name(__FUNCTION__); //輸出:myfunc
}
void foo()
{
show_name(__FUNCTION__); //輸出:foo
}
因為 __FUNCTION__ 會在函數大括號開始之后就立即初始化,所以,foo()及myfunc()函數可在參數列表中安全地使用它,而不用擔心重載。
  簽名與修飾名
   __FUNCTION__ 特性最初是為C語言設計的,然而,C++程序員也會經常需要有關他們函數的額外信息,在Visual Studio 2005中,還支持另外兩種非標準的擴展特性:__FUNCDNAME__ 與 __FUNCSIG__ ,其分別轉譯為一個函數的修飾名與簽名。函數的修飾名非常有用,例如,在你想要檢查兩個編譯器是否共享同樣的ABI時,就可派得上用場,另外,它還能幫助 你破解那些含義模糊的鏈接錯誤,甚至還可用它從一個DLL中調用另一個用C++鏈接的函數。在下例中,show_name()報告了函數的修飾名:
void myfunc()
{
show_name(__FUNCDNAME__); //輸出:?myfunc@@YAXXZ
}
一 個函數的簽名由函數名、參數列表、返回類型、內含的命名空間組成。假如它是一個成員函數,它的類名和const/volatile限定符也將是簽名的 一部分。以下的代碼演示了一個獨立的函數與一個const成員函數簽名間的不同之處,兩個函數的名稱、返回類型、參數完全相同:
void myfunc()
{
show_name(__FUNCSIG__); // void __cdecl myfunc(void)
}
struct S
{
void myfunc() const
{
show_name(__FUNCSIG__); //void __thiscall S::myfunc(void) const
}
};



posted on 2012-06-28 16:10 多彩人生 閱讀(386) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

統計

常用鏈接

留言簿(3)

隨筆分類

隨筆檔案

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品sss| 久久成人精品电影| 国产精品蜜臀在线观看| 欧美xart系列高清| 久久久青草青青国产亚洲免观| 中文在线资源观看视频网站免费不卡| 亚洲欧洲日本专区| 欧美a级片网站| 免费人成精品欧美精品| 欧美激情一区二区| 亚洲欧洲一区二区三区| 99视频+国产日韩欧美| 亚洲一级在线观看| 欧美中日韩免费视频| 久久一区激情| 欧美激情视频一区二区三区免费 | 欧美系列电影免费观看| 欧美午夜精品| 国产一级久久| 亚洲黄色免费电影| 一区二区三区精品国产| 久久国产精品99精品国产| 欧美mv日韩mv国产网站app| 亚洲精品网站在线播放gif| 亚洲免费在线观看视频| 麻豆精品一区二区av白丝在线| 国产精品成人在线观看| 亚洲欧美一区二区三区极速播放| 欧美影视一区| 欧美好骚综合网| 国产精品手机视频| 亚洲国产老妈| 欧美在线精品一区| 亚洲人成精品久久久久| 欧美一二三区精品| 欧美日韩午夜精品| 亚洲第一福利视频| 欧美在线你懂的| 亚洲美女精品一区| 老鸭窝91久久精品色噜噜导演| 国产精品电影网站| 99视频一区| 女生裸体视频一区二区三区| 亚洲女人天堂av| 欧美午夜电影网| 一区二区三区国产盗摄| 欧美高清视频在线| 久久久999精品视频| 国产精品入口日韩视频大尺度| 亚洲精品日本| 亚洲福利电影| 美女国产一区| 亚洲国产成人午夜在线一区 | aa日韩免费精品视频一| 欧美国产成人精品| 老司机久久99久久精品播放免费 | 在线亚洲免费视频| 亚洲欧美成人在线| 欧美精品一区二区三区在线播放| 国产一区再线| 西西人体一区二区| 在线视频精品一区| 欧美日韩亚洲一区在线观看| 亚洲欧洲日夜超级视频| 亚洲国产成人一区| 欧美国产综合| av成人老司机| 一本久久综合亚洲鲁鲁| 欧美精品在线观看播放| 亚洲免费av网站| 亚洲日本成人网| 欧美日韩在线播| 午夜国产一区| 亚洲国产成人精品女人久久久| 欧美成人r级一区二区三区| 亚洲三级免费| 欧美精品日本| 中文国产成人精品久久一| 亚洲日韩欧美一区二区在线| 欧美激情亚洲精品| aa级大片欧美三级| 一卡二卡3卡四卡高清精品视频| 欧美日韩国产亚洲一区 | 国产精品青草久久| 性伦欧美刺激片在线观看| 亚洲欧美色一区| 激情文学一区| 亚洲精品一区二| 国产精品永久免费在线| 狂野欧美一区| 欧美视频在线观看免费| 久久精品一区二区三区中文字幕| 久久久久久久综合日本| 99国产精品久久久| 午夜日韩在线观看| 亚洲精选久久| 亚久久调教视频| 亚洲毛片视频| 99国产精品久久久久久久久久| 国产欧美一区二区三区另类精品| 久久精品中文字幕免费mv| 蜜桃av综合| 亚洲欧美日韩电影| 老鸭窝毛片一区二区三区| 亚洲欧美中文在线视频| 久久一区二区三区四区| 亚洲欧美日韩精品久久| 久久视频一区二区| 中文精品在线| 免费在线欧美视频| 欧美在线亚洲| 欧美系列亚洲系列| 亚洲国产精品视频| 韩国三级电影久久久久久| 日韩视频免费在线观看| 1204国产成人精品视频| 亚洲女人小视频在线观看| 日韩午夜av电影| 老色鬼久久亚洲一区二区| 久久久久国产精品麻豆ai换脸| 欧美午夜无遮挡| 国产精品美女在线观看| 久久免费高清视频| 国产精品久久网| 99精品视频一区| 欧美在线播放一区| 亚洲大片av| 久久蜜桃香蕉精品一区二区三区| 另类尿喷潮videofree| 亚洲欧美日韩精品久久久久| 久久精品中文字幕一区| 欧美影院成人| 国产精品二区在线观看| 亚洲精品免费看| 激情综合中文娱乐网| 亚洲精品欧美激情| 久久久久久久999| 亚洲最新中文字幕| 中文日韩欧美| 欧美一进一出视频| 亚洲国产精品一区| 亚洲图中文字幕| 欧美成人国产| 国产字幕视频一区二区| 99精品久久免费看蜜臀剧情介绍| 亚洲视频视频在线| 欧美亚洲免费在线| 欧美成人情趣视频| 欧美一区二区福利在线| 欧美日韩高清不卡| 91久久精品一区二区别| 久久精品欧洲| 欧美福利电影网| 欧美中文字幕精品| 久久精品一二三区| 久久久久九九视频| 久久激情中文| 欧美激情一区二区在线 | 亚洲在线视频网站| 亚洲视频网站在线观看| 欧美日韩精品综合| 日韩午夜精品视频| 亚洲欧美日韩国产综合精品二区| 国产精品久久久久影院色老大 | 一区二区免费在线观看| 亚洲欧洲精品一区二区三区不卡 | 久久国内精品视频| 国产亚洲免费的视频看| 久久亚洲精品网站| 亚洲乱码国产乱码精品精天堂| 亚洲视频电影图片偷拍一区| 国产精品丝袜久久久久久app| 久久精品日韩| 日韩视频中文| 久久在线免费观看| 亚洲伊人色欲综合网| 一区二区三区在线视频观看| 欧美高清一区| 亚洲欧美在线播放| 亚洲精品久久久久久久久| 亚洲欧美日韩综合| 亚洲国产日韩一级| 国产精品每日更新| 欧美电影在线播放| 性感少妇一区| 亚洲肉体裸体xxxx137| 久久激五月天综合精品| 亚洲视频免费在线| 亚洲激情视频网| 国产一区二区三区在线观看免费| 欧美激情综合在线| 久久天天综合| 欧美中文字幕在线播放| 在线一区二区三区四区| 亚洲国产一区二区精品专区| 久久久久国产一区二区| 亚洲一区黄色| 一二三区精品| 亚洲第一久久影院| 韩国av一区二区三区|