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

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夜夜| 欧美精品日韩一本| 国产伦精品一区二区三区四区免费| 国产情侣久久| 国产亚洲精品一区二区| 亚洲人成人77777线观看| 亚洲影视九九影院在线观看| 久久国产精品久久w女人spa| 欧美韩日一区二区三区| 中文在线资源观看网站视频免费不卡| 午夜精品久久久久久久| 欧美黄色aa电影| 国产日韩综合一区二区性色av| 亚洲激情女人| 久久精品国产精品亚洲精品| 亚洲欧洲精品成人久久奇米网| 亚洲精品午夜| 久久精品在线播放| 国产精品捆绑调教| 亚洲国产天堂久久综合| 久久国产成人| 亚洲视频免费观看| 欧美国产成人在线| 亚洲电影中文字幕| 久久大逼视频| 亚洲深夜av| 欧美视频你懂的| 亚洲久久视频| 欧美激情一区二区三区在线视频| 西西裸体人体做爰大胆久久久| 欧美精品福利| 亚洲人体影院| 蜜臀av在线播放一区二区三区| 亚洲免费在线精品一区| 免费久久99精品国产| 红桃视频国产一区| 久久久国产精品一区二区中文| 精品福利电影| 久久久久久久久久久一区| 亚洲一区在线播放| 欧美视频导航| 亚洲欧美日韩精品一区二区| 亚洲美女av在线播放| 欧美激情精品久久久久久大尺度| 在线免费观看欧美| 欧美成人免费播放| 免费欧美日韩| 亚洲人永久免费| 欧美激情五月| 欧美理论电影在线观看| 一区二区三区高清在线| 99re成人精品视频| 欧美性做爰猛烈叫床潮| 午夜精品久久久久久久久久久久久| 一本色道久久加勒比精品| 欧美午夜视频一区二区| 亚洲一区二区三区成人在线视频精品| 日韩天堂在线视频| 国产精品你懂的在线| 欧美在线观看视频| 久久精品道一区二区三区| 红桃视频成人| 亚洲人成在线观看一区二区| 欧美日韩国产在线观看| 亚洲一区视频在线观看视频| 亚洲免费综合| 玉米视频成人免费看| 亚洲高清久久网| 欧美日韩另类在线| 久久成人精品无人区| 欧美一区二视频| 在线播放国产一区中文字幕剧情欧美 | 欧美激情精品久久久久久久变态| 亚洲精品在线三区| 一区二区三区四区国产| 国产一区二区三区精品欧美日韩一区二区三区| 久久成人免费电影| 欧美大片在线看免费观看| 亚洲一区免费看| 久久青青草综合| 亚洲视频在线观看| 午夜视频久久久| 亚洲欧洲另类| 午夜精品短视频| aⅴ色国产欧美| 久久成人国产| 亚洲男人第一网站| 免费欧美网站| 久久电影一区| 欧美日韩国产成人精品| 久久婷婷久久一区二区三区| 欧美日韩亚洲一区三区| 久久久久久成人| 国产精品v片在线观看不卡 | 久久夜色精品| 亚洲午夜在线观看视频在线| 韩国v欧美v日本v亚洲v| 日韩亚洲欧美成人| 在线视频国内自拍亚洲视频| 亚洲一级二级| 亚洲视频国产视频| 欧美大片免费| 蜜臀久久99精品久久久久久9 | 国内偷自视频区视频综合| 日韩视频一区二区三区在线播放| 一区二区三区在线免费视频| 亚洲视频在线免费观看| 日韩午夜一区| 免费看av成人| 欧美超级免费视 在线| 国产一区二区高清视频| 亚洲自啪免费| 亚洲欧美日韩成人高清在线一区| 欧美成人日韩| 亚洲承认在线| 亚洲国产日韩欧美在线动漫 | 国产精品扒开腿做爽爽爽软件 | 国内精品久久久久久久影视蜜臀| 一本色道久久综合亚洲精品不卡| 亚洲日本理论电影| 男人的天堂成人在线| 欧美高清视频www夜色资源网| 怡红院av一区二区三区| 久久久久久久久伊人| 久久人体大胆视频| 精品不卡在线| 美女久久一区| 91久久精品视频| 亚洲天堂偷拍| 国产精品五月天| 欧美一级片在线播放| 久久久久久久一区| 尤物yw午夜国产精品视频明星| 久久久午夜视频| 欧美激情第六页| 一区二区三区四区精品| 国产精品黄视频| 午夜欧美精品久久久久久久| 久久影视精品| 亚洲精品久久视频| 欧美激情a∨在线视频播放| 亚洲精品一区二区三区婷婷月| 中国女人久久久| 国产视频欧美| 老司机久久99久久精品播放免费 | 欧美日韩三级在线| 亚洲影院免费观看| 久久夜色精品国产欧美乱| 亚洲成色最大综合在线| 欧美精品亚洲精品| 亚洲视频综合| 麻豆亚洲精品| 亚洲视频第一页| 国产性猛交xxxx免费看久久| 免费一级欧美片在线观看| 在线一区二区三区四区五区| 国产日韩在线一区二区三区| 久久乐国产精品| 99国产精品国产精品久久| 久久大逼视频| 日韩亚洲综合在线| 国产欧美日韩视频| 免费影视亚洲| 亚洲欧美一区二区三区在线| 亚洲国产99| 久久久女女女女999久久| 一本久久a久久精品亚洲| 黄色成人在线网站| 国产精品mm| 欧美成在线观看| 久久精品国产免费观看| 亚洲毛片播放| 欧美高清视频一区二区| 久久gogo国模啪啪人体图| 亚洲精品精选| 红桃视频欧美| 国产日韩欧美在线播放不卡| 欧美喷潮久久久xxxxx| 久久久久国产精品一区| 亚洲一区3d动漫同人无遮挡| 亚洲欧洲在线视频| 男人的天堂成人在线| 欧美一区二区黄| 亚洲一区二区三区免费在线观看| 亚洲国产精品一区制服丝袜| 国产婷婷精品| 国产精品日本精品| 欧美视频免费在线观看|