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

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>
            久久影视三级福利片| 一二三区精品| 99国产一区| 91久久精品日日躁夜夜躁欧美| 国产精品自在在线| 国产精品一区二区久久久| 国产伦精品一区二区三| 国产亚洲一级高清| 一区二区亚洲欧洲国产日韩| 亚洲国产高清一区二区三区| 亚洲精品影视| 新片速递亚洲合集欧美合集| 久久精品30| 激情成人综合| 亚洲高清在线观看| 亚洲天堂网站在线观看视频| 亚洲欧美制服另类日韩| 久久久无码精品亚洲日韩按摩| 免费观看30秒视频久久| 亚洲精品免费一二三区| 亚洲毛片av| 亚洲专区在线视频| 免费成人av| 国产美女扒开尿口久久久| 黄色在线一区| 亚洲一区欧美一区| 免费欧美高清视频| 亚洲网站在线| 欧美成ee人免费视频| 国产精品一页| 99视频精品在线| 久久久噜噜噜久久中文字免| 日韩亚洲欧美综合| 久久日韩精品| 国产精品在线看| 亚洲激情av在线| 久久久久久久久蜜桃| 在线综合+亚洲+欧美中文字幕| 久久综合狠狠综合久久综合88 | 久久久久久久久综合| 欧美激情按摩| 激情欧美日韩一区| 欧美一区二区三区在线| 亚洲国产精品成人久久综合一区| 午夜精品久久久久久久久久久| 欧美另类一区二区三区| 在线日韩欧美| 久久免费视频一区| 午夜精品视频在线观看| 国产精品成av人在线视午夜片| 亚洲七七久久综合桃花剧情介绍| 欧美国产视频日韩| 亚洲免费视频在线观看| 欧美日韩视频第一区| 亚洲国产精品成人一区二区| 久久精品国产成人| 亚洲欧美美女| 国产精品欧美久久久久无广告| 9色国产精品| 亚洲黄色天堂| 欧美国产日韩二区| 亚洲精一区二区三区| 欧美激情第六页| 免费观看在线综合| 亚洲日本免费电影| 91久久久国产精品| 欧美精品日韩三级| 在线一区二区三区四区| 亚洲精品欧美日韩专区| 欧美裸体一区二区三区| 一区二区三区精品视频| 一区二区三区欧美成人| 国产精品视频一区二区三区| 亚洲欧美视频在线观看视频| 在线视频精品一| 国产精品色婷婷久久58| 欧美专区第一页| 久久精品一区二区| 亚洲经典在线看| 亚洲毛片在线观看| 国产精品99一区| 久久精品99国产精品| 久久久久久久999| 日韩视频免费看| 中国成人在线视频| 国内一区二区在线视频观看 | 欧美日本不卡| 亚洲一区日韩在线| 欧美一区不卡| 亚洲人成网站精品片在线观看| 亚洲全部视频| 国产伦一区二区三区色一情| 久久精品视频在线免费观看| 久久五月激情| 亚洲综合电影| 玖玖玖免费嫩草在线影院一区| 99国产精品久久| 欧美一级片一区| 在线视频亚洲| 久久精品99无色码中文字幕| 欧美天天在线| 久久久久久色| 欧美人在线观看| 久久久久久久综合日本| 欧美日韩国产免费观看| 久久久久女教师免费一区| 欧美高清hd18日本| 久久国产免费| 欧美性猛交99久久久久99按摩| 久久成人免费电影| 欧美精品粉嫩高潮一区二区| 久久精品国产亚洲5555| 亚洲免费观看高清完整版在线观看熊| 99视频精品| 怡红院精品视频在线观看极品| 91久久久久久久久| 国内精品伊人久久久久av一坑| 91久久久久久久久久久久久| 国产亚洲欧洲一区高清在线观看| 亚洲日本va午夜在线电影| 黄色成人免费观看| 午夜精品久久久久久99热| 一级成人国产| 欧美黑人国产人伦爽爽爽| 久久资源在线| 国产伊人精品| 欧美一区二区观看视频| 午夜影视日本亚洲欧洲精品| 欧美日韩国产精品一区| 亚洲日本电影| 亚洲久久一区| 欧美精品一区视频| 亚洲精品视频免费在线观看| 国产中文一区| 欧美在线视频a| 久久久久久久国产| 狠狠色香婷婷久久亚洲精品| 欧美与黑人午夜性猛交久久久| 欧美一区二区成人6969| 国产九九精品| 午夜综合激情| 久久亚洲精品网站| 在线日韩成人| 欧美精品一区二区三区久久久竹菊| 亚洲第一搞黄网站| 亚洲深夜激情| 国产精品视频第一区| 亚洲欧美日韩精品在线| 久久久精品午夜少妇| 雨宫琴音一区二区在线| 免费在线视频一区| 亚洲免费成人av电影| 午夜精品国产更新| 国内精品一区二区三区| 欧美国产成人精品| 在线亚洲国产精品网站| 久久se精品一区二区| 国产一区二区av| 快she精品国产999| 亚洲美女在线看| 欧美一级精品大片| 精品不卡一区| 欧美激情第五页| 午夜精品视频网站| 亚洲大片精品永久免费| 夜夜嗨av一区二区三区免费区| 国产精品va在线| 久久久999国产| 亚洲激情视频网站| 亚洲欧美精品suv| 怡红院精品视频在线观看极品| 欧美国内亚洲| 欧美一级久久| 亚洲精品免费在线播放| 欧美一级夜夜爽| 在线免费观看日韩欧美| 欧美日韩综合| 久久综合精品国产一区二区三区| 日韩午夜一区| 欧美高清自拍一区| 午夜性色一区二区三区免费视频| 在线观看一区二区视频| 在线观看欧美日韩| 国产精品乱看| 久久亚洲美女| 亚洲一区二区三区免费视频| 久久免费99精品久久久久久| 99精品国产在热久久下载| 国产视频久久久久| 欧美日本簧片| 免费日韩av片| 久久黄色影院| 中文在线资源观看视频网站免费不卡| 久久亚洲图片| 性欧美video另类hd性玩具| 日韩一级欧洲| 亚洲国产日韩一区| 韩国三级电影久久久久久| 国产精品国产三级国产普通话三级| 久久久综合网站|