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

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>
            久久成人综合视频| 欧美日韩国产成人在线观看| 亚洲精品在线电影| 国产精品激情电影| 亚洲一区二区综合| 激情综合视频| 韩国在线视频一区| 国产一区二区剧情av在线| 久久字幕精品一区| 久久综合网络一区二区| 久久九九久久九九| 一本久久知道综合久久| 亚洲一区在线直播| 性做久久久久久久免费看| 午夜在线不卡| 性色av一区二区三区| 亚洲在线第一页| 久久精品免费电影| 久久久久九九九| 久久久免费精品| 欧美精品三区| 久久婷婷国产综合精品青草| 亚洲激情二区| 亚洲国产三级网| 欧美激情国产日韩| 最新日韩欧美| 亚洲图片欧美一区| 久久se精品一区二区| 国产精品99久久久久久久vr | 久久久www成人免费无遮挡大片 | 久久精品人人做人人爽电影蜜月| 欧美极品在线视频| 亚洲图片欧美午夜| 亚洲国产成人午夜在线一区| 亚洲欧洲综合| 国产精品私拍pans大尺度在线| 亚洲国产免费| 亚洲第一页中文字幕| 欧美一区2区三区4区公司二百| 国产亚洲欧美另类中文| 国产精品一区在线观看你懂的| 国产精品视频yy9099| 久久久亚洲一区| 欧美精品1区2区3区| 国产精品日韩一区二区三区| 午夜精品久久久久久久男人的天堂 | 一区二区三区**美女毛片 | 亚洲精品永久免费| 国产亚洲亚洲| 欧美在线视频导航| 久久久一二三| 国产欧美视频一区二区三区| 亚洲午夜精品久久久久久浪潮| 久久国产色av| 国产亚洲精品自拍| 欧美日本精品一区二区三区| 玖玖综合伊人| 伊人久久综合| 国产嫩草一区二区三区在线观看| 老鸭窝91久久精品色噜噜导演| 亚洲成人资源| 亚洲国产二区| 国产精品www网站| 国产亚洲福利社区一区| 国产揄拍国内精品对白| 欧美日韩日本视频| 国产一区美女| 亚洲欧美美女| 久久精品天堂| 欧美精品v日韩精品v国产精品| 一区二区三区不卡视频在线观看| 欧美黄免费看| 亚洲国产一区二区三区青草影视 | 巨乳诱惑日韩免费av| 亚洲欧美另类在线观看| 一区二区电影免费在线观看| 国产综合色精品一区二区三区| 99国产精品久久久久久久成人热| 久久er99精品| 欧美成人第一页| 亚洲欧美日韩第一区| 欧美激情精品久久久| 91久久国产自产拍夜夜嗨| 国产精品欧美在线| 在线综合+亚洲+欧美中文字幕| 久久精品视频在线播放| 久久久久久9999| 伊人精品视频| 国产精品普通话对白| 另类天堂av| 日韩一区二区福利| 亚洲精品日韩久久| 欧美一区二区三区精品电影| 欧美日韩另类丝袜其他| 亚洲一区久久| 国产精品欧美日韩一区二区| 免费在线看成人av| 久久久久天天天天| 国产精品v欧美精品∨日韩| 欧美一区二区在线视频| 国产精品系列在线| 一区二区国产在线观看| 国产视频久久久久久久| 国产一区二区三区在线观看网站 | 亚洲激情成人在线| 国产一区二区三区四区五区美女| 欧美夜福利tv在线| 欧美三级电影精品| 欧美午夜电影在线| 日韩一区二区电影网| 99精品欧美一区二区三区综合在线| 在线观看福利一区| 欧美一二三区在线观看| 亚洲精品久久久蜜桃| 国产精品自在线| 国产九九视频一区二区三区| 国产日本亚洲高清| 亚洲日本va午夜在线影院| 欧美日韩无遮挡| 欧美大片在线看免费观看| 欧美性大战久久久久久久| 欧美国产精品va在线观看| 伊人成人在线视频| 欧美成人性网| 99这里有精品| 乱中年女人伦av一区二区| 欧美一区二区精品| 亚洲日本一区二区三区| 亚洲美女少妇无套啪啪呻吟| 亚洲午夜一区二区三区| 亚洲一区二区在| 欧美成人日韩| 免费欧美在线视频| 亚洲国产婷婷| 久久亚洲高清| 一区二区不卡在线视频 午夜欧美不卡'| 国产自产精品| 国产主播喷水一区二区| 欧美精品久久一区| 中日韩高清电影网| 亚洲国产精品久久久久婷婷老年 | 欧美在线你懂的| 久久久精品国产免大香伊| 一本色道久久88综合亚洲精品ⅰ | 亚洲精美视频| 欧美日韩精品一本二本三本| 99视频在线观看一区三区| 亚洲视频一二三| 亚洲精品黄网在线观看| 久久久免费观看视频| 久久久久9999亚洲精品| 欧美系列电影免费观看| 亚洲黄色影院| 亚洲精品国产系列| 亚洲综合二区| 午夜精品999| 国产精品国产三级国产aⅴ无密码| 欧美高清自拍一区| 亚洲第一页在线| 久久三级视频| 六月天综合网| 国产精品毛片一区二区三区| 一区二区三区视频在线播放| 亚洲精品久久久久久久久| 午夜亚洲福利| 久久久久久欧美| 国产精品尤物福利片在线观看| 在线视频欧美日韩| 亚洲视频一区二区| 国产精品国产三级国产普通话蜜臀 | 一区二区三区日韩欧美| 免费不卡视频| 亚洲国产另类精品专区| 国产亚洲综合性久久久影院| 亚洲在线观看视频| 久久国产色av| 伊人久久婷婷色综合98网| 亚洲一区二区免费看| 亚洲国产精品美女| 免费国产一区二区| 亚洲精品久久久久中文字幕欢迎你| 亚洲精品美女| 久久久久一区二区三区| 男人的天堂亚洲| 亚洲精品一区久久久久久| 欧美另类一区| 麻豆精品国产91久久久久久| 国产欧美亚洲精品| 久久久九九九九| 亚洲高清免费| 香蕉久久夜色精品国产| 极品裸体白嫩激情啪啪国产精品| 美日韩丰满少妇在线观看| 亚洲精品系列| 午夜视频一区二区| 好看的亚洲午夜视频在线| 欧美.日韩.国产.一区.二区| 亚洲桃花岛网站| 欧美成人dvd在线视频| 在线亚洲美日韩|