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

woaidongmao

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

VC中一個關(guān)于宏的使用問題

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

posted on 2010-07-10 02:05 肥仔 閱讀(390) 評論(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>
            国产欧美一区二区三区在线老狼| 在线一区观看| 99视频精品免费观看| 亚洲人人精品| 在线中文字幕日韩| 亚洲一区久久久| 欧美制服丝袜第一页| 久久在线播放| 欧美成人中文| 欧美高清在线视频| 亚洲国产一区视频| 亚洲国产高清自拍| 日韩视频中午一区| 香蕉成人伊视频在线观看| 久久天堂精品| 欧美午夜精彩| 激情欧美丁香| 在线亚洲电影| 久久久亚洲一区| 亚洲人成网站999久久久综合| 一区二区三区视频观看| 久久免费观看视频| 国产精品mm| 亚洲欧洲一区二区三区在线观看| 中文亚洲免费| 欧美成人精品福利| 亚洲一级特黄| 欧美日韩不卡一区| 在线观看91精品国产麻豆| 亚洲素人一区二区| 欧美成人亚洲| 欧美一区精品| 国产精品久久久久影院色老大 | 久久亚洲综合色| 亚洲乱码国产乱码精品精可以看 | 亚洲永久免费精品| 欧美精品麻豆| 91久久久一线二线三线品牌| 亚洲欧美高清| 亚洲精品一区二区三区蜜桃久| 欧美在线一二三| 国产精品成人一区二区艾草| 亚洲精品一区二区三区av| 久久一区二区精品| 午夜亚洲视频| 国产午夜精品全部视频在线播放| 夜夜嗨av一区二区三区四季av| 猛干欧美女孩| 久久久久久亚洲精品中文字幕| 国产情人综合久久777777| 亚欧成人精品| 亚洲欧美国产精品桃花| 国产精品手机视频| 午夜在线视频一区二区区别| 亚洲视频高清| 国产精品入口麻豆原神| 午夜精品成人在线视频| 一本一道久久综合狠狠老精东影业 | 午夜欧美电影在线观看| 欧美特黄一区| 亚洲一级黄色av| 99国产精品国产精品毛片| 欧美日韩美女在线| 亚洲综合欧美日韩| 亚洲欧美日韩国产成人| 国产一区二区日韩精品欧美精品| 久久九九99| 久久久精品五月天| 亚洲欧洲在线看| 亚洲毛片在线观看| 国产精品v片在线观看不卡| 欧美一区二区在线视频| 久久精品91| 亚洲片国产一区一级在线观看| 亚洲日本欧美日韩高观看| 欧美人与禽性xxxxx杂性| 亚洲一区二区三区激情| 亚洲欧美另类中文字幕| 黑人操亚洲美女惩罚| 欧美激情一区二区三级高清视频| 欧美—级高清免费播放| 午夜精品一区二区三区四区| 羞羞答答国产精品www一本| 精品96久久久久久中文字幕无| 亚洲国产精品成人久久综合一区| 欧美日韩精品综合| 久久精品在线视频| 欧美韩国一区| 久久国产福利| 欧美日韩国产bt| 久久久久成人精品| 欧美国产1区2区| 久久精品国产久精国产一老狼| 久久婷婷色综合| 亚洲在线黄色| 嫩模写真一区二区三区三州| 亚洲一区二区三区欧美| 久久国产精品一区二区三区| 宅男精品导航| 久久久综合视频| 午夜精品www| 欧美韩日亚洲| 欧美 日韩 国产 一区| 国产精品久久一区主播| 亚洲高清二区| 极品av少妇一区二区| 亚洲一区二区成人在线观看| 亚洲精选一区| 久久网站热最新地址| 午夜在线一区| 国产精品豆花视频| 亚洲人成网站777色婷婷| 好吊妞这里只有精品| 亚洲综合成人在线| 亚洲一区精品视频| 欧美日本中文| 亚洲国产导航| 亚洲激情另类| 久久久噜噜噜久久狠狠50岁| 欧美.日韩.国产.一区.二区| 亚洲精品在线视频| 久久精品欧美日韩| 久久精品国产久精国产一老狼| 国产精品国产三级国产专区53| 亚洲激情视频在线观看| 亚洲国产精品成人精品| 久久久久久自在自线| 久久精品一本| 国产日韩欧美日韩大片| 亚洲欧美日韩精品综合在线观看| 亚洲愉拍自拍另类高清精品| 欧美色视频在线| 在线视频一区二区| 午夜久久久久久| 国产精品午夜av在线| 亚洲欧美韩国| 久久久久久久一区二区| 狠狠色综合色综合网络| 久久综合电影| 欧美丰满高潮xxxx喷水动漫| 亚洲国产精品一区二区www在线 | 午夜精品久久久久| 欧美视频在线视频| 亚洲女人天堂av| 久久精品一区二区三区不卡牛牛| 国产亚洲aⅴaaaaaa毛片| 久久久999精品| 韩国v欧美v日本v亚洲v| 久久久久久久综合色一本| 欧美高清成人| 亚洲精品在线看| 欧美午夜激情在线| 羞羞视频在线观看欧美| 男女精品网站| 一区二区三区高清在线观看| 久久精品国产免费看久久精品| 欧美插天视频在线播放| 欧美日韩一本到| 亚洲综合清纯丝袜自拍| 六月丁香综合| aa级大片欧美三级| 国产精品一区二区a| 久久久91精品国产| 亚洲第一黄色网| 亚洲香蕉成视频在线观看| 国产综合精品一区| 欧美国产亚洲视频| 亚洲一区久久久| 欧美高清视频在线| 亚洲欧美日本精品| 亚洲国产日韩欧美| 国产精品资源| 欧美人妖在线观看| 久久全球大尺度高清视频| 亚洲精品在线视频| 久久亚洲一区二区| 亚洲一区二区三区免费在线观看| 韩国三级电影久久久久久| 欧美日韩高清在线| 老司机午夜精品| 亚洲欧美一区二区原创| 亚洲日本中文字幕区| 久久中文字幕导航| 午夜亚洲福利在线老司机| 亚洲欧洲三级电影| 国产一区二区你懂的| 久久欧美肥婆一二区| 亚洲一区二区三区中文字幕在线| 亚洲综合国产激情另类一区| 久久久久久久久久久久久久一区| 亚洲电影观看| 久久久综合网站| 亚洲欧美日韩成人高清在线一区| 亚洲国产日韩欧美一区二区三区| 国产日韩精品在线观看| 欧美午夜精品电影| 欧美另类高清视频在线| 牛牛影视久久网| 久久精品免费看| 欧美一区二区三区在线观看|