VC++編譯器中包括一種本機類型,用來支持長字符串,它就是wchar_t,它所佔用的內存長度爲2個字節,同時VC++編譯器2個字節長度的類型有short, unsigned short。(參考鏈接:http://msdn.microsoft.com/zh-cn/library/dh8che7s(VS.80).aspx)它們相互之間其實是可以進行類型轉換而不會發生內存定位錯誤的,如:
(在打開編譯器選項/Zc:wchar_t的情況下)
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
unsigned short *pUShort ; //或是 short *pUShort;
wchar_t *pWChar = L"ABCD";
pUShort = (unsigned short*)pWChar;
MessageBoxW(NULL,(wchar_t*)pUShort, L"ok", 0); //OK,這樣是可以的
return 0;
}
所以,VC++對wchar_t提供了兩種實現方式,
1.以unsinged char 來做爲wchar_t來處理:typedef unsigned char wchar_t ;
2.直接提供wchar_t的本機類型。它由加入/Zc:wchar_t編譯器選項來實現。
爲什麼要這樣做?
它可能是與在X386平臺下的int和long類型的關係一樣,它們的內存空間長度是相同的,但明顯long這個名稱可以給人一種直觀的認識。
那麼這個編譯器選項到底做了什麼呢?
如下函數:
public: virtual long __stdcall CBaseFilter::QueryVendorInfo(wchar_t * *)
在沒有加入/Zc:wchar_t編譯器選項時,編譯器輸出的函數符號爲:
?QueryVendorInfo@CBaseFilter@@UAGJPAPAG@Z
但在加入此選項之後,編譯器輸出的函數符號爲:
?QueryVendorInfo@CBaseFilter@@UAGJPAPA_W@Z
看到了嗎?最後的一個字符是不同的,G(未加選項)_W(加選項)
所以它們的最終輸出的函數符號是不同的,這樣的話,會發生某些情況:
如果生成了一個靜態或是動態庫,它使用unsigned char來實現wchar_t類型,而調用它的程序以本機類型方式來實現wchar_t類型,則在鏈接調用程序時,會發生“unresolved external symbol ”(“無法解析的外部符號”)錯誤。所以在使用wchar_t類型時一定要注意多個工程相互調用時,要將wchar_t的實現方式設置爲相同的。
實際工作中,可能會經常出現的由此原因所產生的錯誤:
directshow所提供的BaseClasses工程就默認將wchar_t設置爲由unsigned short來實現,如果由MFC程序來實現一個direct show工程的話,因爲MFC工程默認將提供wchar_t本機類型。所以如果直接編譯的話,在最後的鏈接過程之中就會發生以下的鏈接錯誤:
MP4MiscRenderer.obj : error LNK2001: 無法解析的外部符號 "public: virtual long __stdcall CBaseFilter::QueryVendorInfo(wchar_t * *)" (?QueryVendorInfo@CBaseFilter@@UAGJPAPA_W@Z)
MP4MiscRenderer.obj : error LNK2001: 無法解析的外部符號 "public: virtual long __stdcall CBaseFilter::JoinFilterGraph(struct IFilterGraph *,wchar_t const *)" (?JoinFilterGraph@CBaseFilter@@UAGJPAUIFilterGraph@@PB_W@Z)
MP4MiscRenderer.obj : error LNK2001: 無法解析的外部符號 "public: virtual long __stdcall CBaseRenderer::FindPin(wchar_t const *,struct IPin * *)" (?FindPin@CBaseRenderer@@UAGJPB_WPAPAUIPin@@@Z)
這是一個很不明顯的錯誤,單從源代碼的角度來看,是無法找出錯誤的位置的。