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

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

VC中一個關于宏的使用問題

這兒是個關于宏的問題,我曾用過ATL的串轉換宏,包括W2A,開始有些東西我還不太明白。為了使用這些宏,必須在函數的開始處用USES_CONVERSION來初始化某些局部變量。用就用吧,但是看看這個宏的定義,它有類似下面的代碼:

// atlconv.h文件中
#define USES_CONVERSION \
int _convert; _convert; \
UINT _acp = GetACP(); _acp; \
LPCWSTR _lpw; _lpw; \?
LPCSTR _lpa; _lpa

為什么它們用“int x;x;”——這種后面跟著變量的聲明? 

   
很多人都碰到過這個令人困惑的問題,后來發現答案很簡單:禁止編譯器的警告信息(warning)。如果單獨有一行代碼:
int x;
且從來沒有使用過x,那么編譯器匯報錯“unreferenced local variablex”,意思是未引用過的局部變量x,如果將警告信息的輸出調到最大。為了避免討厭的警告,USES_CONVERSION引用聲明的變量。

      int x; // 聲明
      x;     //
使用這個變量
     

C++之前的時代,程序員有時在C中用函數形參做同樣的事情來避免“unreferenced formal parameter”或其它的深奧費解的編譯錯誤。

void MyFunc(int x, char y)
{
  x;
  y;
  ......
}

當然,現在用下面的代碼可以更有效地完成同樣的事情:

// 參數 x 不是用
void MyFunc(int /* x */)
{
   ......
}    

    也就是說聲明參數,但不給它起名,不能這樣使用局部變量;必須顯式地引用它。這樣做不會增加任何指令到代碼中。最多可能多增加幾個字節到堆棧(為x預留空 間)。靈巧的編譯器甚至不會操心x從來沒有被使用過——雖然好奇心可能想知道:如果編譯器夠厲害,知道了從沒有使用x,為什么要抱怨(編譯出錯)呢?答案是因為苛刻的程序員(且編程能力與個人的記性有關)使用編譯警告提醒自己刪除某部分代碼時發生變量荒廢。這種警告在C時代很有用,你必須在每個函數的頂部聲明變量,這就遠離了實用它們的代碼。
   
現在來看看另一個問題:為什么在開始位置要用USES_CONVERSION?即為什么W2A&Co之類的宏還需要另外的宏聲明自己的變量;為什么不直接在W2A中聲明這個變量?

#define W2A(x) \
int _convert; _convert; \
……etc

很明顯這樣做不行,因為如果你使用W2A兩次,得到一個復制的變量。那為什么不把整個宏放進花括弧創建新的范圍?

#define W2A(x) Q{ \
int _convert; _convert; \
…… \
}

這樣解決了命名沖突,但不能進行如下編碼:
DoSomething(W2A(pwstr));
沒有辦法從代碼塊返回值,所以不能在函數調用中傳遞W2A。真笨啊,那么內聯函數怎么樣?

inline LPCSTR W2A(LPWSTR w) {
int_convert;
……
}

    這解決了范圍問題——任何W2A需要的變量多可以在這個函數中,在自己的范圍內聲明,不需要另外的宏。它也提供了一種返回值的方式,使你可以在函數調用和賦值中使用W2Ax)。但是這種方法不靈,也是因為W2A的緣故和其它的宏更復雜。
不管什么時候進行Unicode轉換,都不能就地轉換串,必須分配一個臨時串容納被轉換的字節。典型地,通過調用new分配一個串:

int len = MultiByteToWideChar(...,?
mystr, NULL, 0); //
或的長度
LPWSTR p = new WCHAR[nLen]; //
分配內存
MultiByteToWideChar(...,p,len); //
轉換
SomeCOMFunction(p); //
使用之
delete [] p; //
銷毀

    這段代碼不僅令人討厭,而且還沒有效率;必須調用MultiByteToWideChar兩次(一次是計算長度,一次是實際的轉換),你得從堆中分配p, 這樣很慢。通過分配2*len個字節解決第一個問題,這里長度lenASCII串的長度——但第二個問題怎么辦?如果看看A2W是如何展開的,請看:

// 簡化版
#define A2W(s) \
_len = 2*strlen(s);
AfxA2WHelper((LPWSTR)alloca(_len);

    AfxA2Whelper是一個調用MultiByteToWideChar的輔助函數。A2W使用2*len巧妙地避免了兩次調用 MultiByteToWideChar。但A2W及其它轉換宏真正聰明的地方是不調用new操作分配臨時串,而是調用alloca——在棧中分配字節, 而不是在堆中。這樣做非常快,因為編譯器要做的只是增加棧指針。不調用函數,不處理內存塊。它也避免了內存碎片,并且也沒有必要調用delete操作,因 為當控制離開alloca被調用的地址后,內存被自動釋放。這正好說明了為什么A2W不能時內聯函數;如果是的話,alloca創建的臨時串會在返回前被 摧毀,并且你會以刪除串的方式終止SomeCOMFunction(使用這個例子)調用。
A2W
必須從alloca被調用的相同的地址處調用alloca——所以A2W必須是一個宏,不是一個函數;因此它需要另一個宏 USERS_CONVERSION來聲明_len以及其它一些用到的變量(為了簡化,我省略了)。當你仔細想想,整個處理告訴我們要想寫一組類似A2W的 宏從棧中的分配內存會減少很多不必要的麻煩。
另外,任何時候,只要你想要快速地獲取臨時內存,都可以調用alloca。下面的代碼是我們常常見到的:

char* p = new char[len];
DoSomething(p);
delete [] p;

使用下面的代碼替代之會效率更高:

char *p = (char*)alloca(len);
DoSomething(p);
//
不用調用delete p!

    當然,如果棧中的沒那么多,你還這么做的話,就會出現一個討厭的消息框。這個方法還有一些局限,詳細內容請參考文檔。經驗告訴我,不管什么時候在MFCATL或其它什么地方發現奇怪的事情,最好是鉆進去研究一下,你可能會發現有用的東西。

posted on 2010-07-10 02:05 肥仔 閱讀(393) 評論(0)  編輯 收藏 引用 所屬分類: MFC存檔

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美精品日韩| 亚洲一区二区三区高清| 欧美激情一区二区三区| 久久亚洲不卡| 欧美理论电影网| 欧美视频二区| 欧美午夜视频在线观看| 国产午夜精品理论片a级探花| 国产婷婷精品| 91久久精品美女| 亚洲午夜一二三区视频| 欧美一区激情| 美女网站在线免费欧美精品| 久久精品噜噜噜成人av农村| 欧美不卡视频一区发布| 亚洲精品国产精品乱码不99按摩| 亚洲另类自拍| 午夜精品久久久久久久99樱桃 | 亚洲视屏在线播放| 欧美亚洲在线| 亚洲电影免费观看高清完整版| 亚洲欧洲久久| 欧美在线视频日韩| 欧美大片免费观看在线观看网站推荐| 欧美性淫爽ww久久久久无| 国产一区二区三区自拍 | 欧美日韩国产小视频| 国产精品视频免费观看www| 亚洲欧美日韩一区二区三区在线| 午夜影院日韩| 欧美日韩精品一二三区| 国产在线精品二区| 中文在线不卡| 欧美激情一区二区三区高清视频| 亚洲无亚洲人成网站77777| 老司机亚洲精品| 国产色爱av资源综合区| 一区二区三区视频在线看| 欧美a级片网站| 午夜精品久久久久久久99黑人| 欧美日韩大片| 99re在线精品| 亚洲福利电影| 久久综合狠狠综合久久综合88| 国产精品久久久久久久久久久久久久| 91久久精品日日躁夜夜躁国产| 久久久久久**毛片大全| 亚洲一二三四久久| 欧美特黄一级大片| 亚洲深夜av| 一本色道久久综合| 欧美精品二区| 亚洲最新视频在线| 亚洲国产精品一区二区第四页av | 亚洲视频综合在线| 欧美片在线观看| 99re6热只有精品免费观看| 免费的成人av| 久久看片网站| 91久久精品国产91性色tv| 米奇777在线欧美播放| 欧美一区深夜视频| 国模吧视频一区| 久久影院午夜片一区| 久久国产精品高清| 一区二区亚洲| 亚洲电影有码| 欧美成人亚洲成人| 日韩视频中文| 在线视频欧美一区| 国产精品揄拍一区二区| 久久激情五月激情| 久久手机精品视频| 亚洲精品国产精品乱码不99按摩| 亚洲欧洲日本mm| 国产精品第2页| 欧美亚洲日本网站| 久久精品综合一区| 亚洲精品国产精品国自产观看 | 亚洲欧美怡红院| 亚洲男女自偷自拍| 国产在线一区二区三区四区| 男女视频一区二区| 亚洲精品久久久蜜桃| 欧美视频在线免费| 欧美尤物一区| 你懂的视频一区二区| 一区二区精品国产| 亚洲一卡二卡三卡四卡五卡| 狠狠久久婷婷| 亚洲精选久久| 国户精品久久久久久久久久久不卡| 欧美电影美腿模特1979在线看 | 久久久亚洲一区| 一区二区三区四区五区在线| 午夜精品影院| 日韩视频第一页| 欧美一区二区三区精品| 亚洲理伦在线| 久久国产手机看片| 一区二区三区蜜桃网| 欧美主播一区二区三区| 日韩视频一区二区三区在线播放| 亚洲一区中文| 制服丝袜激情欧洲亚洲| 久久国产乱子精品免费女 | 亚洲成色最大综合在线| 国产精品欧美风情| 亚洲国产精品日韩| 极品少妇一区二区三区| 这里只有精品视频| 亚洲日本va午夜在线影院| 欧美亚洲在线| 亚洲欧美日韩在线| 欧美激情在线观看| 免费看av成人| 国产综合网站| 亚洲欧美精品suv| 中文精品在线| 欧美精品综合| 91久久久久久久久| 在线观看亚洲视频啊啊啊啊| 亚洲免费在线视频| 亚洲欧美日韩国产中文| 欧美日韩精品三区| 亚洲精品永久免费| 亚洲日韩欧美一区二区在线| 久久久91精品国产| 久久久久久一区| 国产日韩亚洲欧美| 亚洲欧美日韩一区二区三区在线观看| 亚洲一区二区三区视频| 欧美日韩国产影院| 日韩系列在线| 亚洲视频一起| 欧美视频在线观看一区二区| 亚洲人成艺术| 亚洲桃花岛网站| 国产精品免费一区豆花| 亚洲性感美女99在线| 午夜视频久久久久久| 国产精品视频免费观看| 午夜日韩在线观看| 久久夜色精品国产欧美乱| 国内精品视频一区| 久久久久久9| 亚洲国产精品久久久久秋霞影院| 亚洲乱码国产乱码精品精可以看| 欧美激情中文不卡| 亚洲美女啪啪| 欧美性理论片在线观看片免费| 亚洲深夜影院| 久久九九热免费视频| 在线看国产一区| 欧美麻豆久久久久久中文| 日韩一级精品| 久久se精品一区精品二区| 在线精品亚洲| 欧美日韩综合网| 午夜精品久久久久久久| 美国十次成人| 正在播放日韩| 狠狠色丁香久久婷婷综合丁香| 久久综合激情| 一区二区三区 在线观看视| 久久精品国产一区二区电影| 亚洲国产精品电影在线观看| 欧美另类一区| 欧美一级久久久| 欧美激情在线| 久久国产一区二区| 日韩视频一区二区三区在线播放免费观看 | 欧美专区18| 亚洲国产综合在线| 欧美在线观看一区二区三区| 亚洲高清网站| 国产精品青草久久| 毛片一区二区三区| 亚洲欧美日韩中文视频| 91久久精品久久国产性色也91| 久久精品99国产精品酒店日本| 日韩特黄影片| 狠狠色丁香婷婷综合| 欧美视频久久| 欧美国产国产综合| 久久激情网站| 亚洲欧美国内爽妇网| 亚洲精品一区二区网址| 欧美电影在线播放| 久久精品视频免费播放| 中文亚洲视频在线| 亚洲另类一区二区| 伊伊综合在线| 激情欧美亚洲| 国产精品一区一区三区| 欧美日韩一区二区三区| 免费一级欧美在线大片| 久久久久久色| 久久精品视频免费播放| 亚洲欧美日韩国产中文|