確切說,GetModuleFileName的定義是壹個宏,在UNICODE版本下,GetModuleFileName等同於GetModuleFileNameW,在ANSI版本下等同於GetModuleFileNameA。
GetModuleFileNameA和GetModuleFileNameW的區別在於它們的字符串參數的“字符寬度”,這兩個函數的原型如下:
DWORD?WINAPI?GetModuleFileNameA(?HMODULE?hModule,?LPSTR
lpFilename,?DWORD?nSize?);//ANSI版本,第二個參數是LPSTR,也就是char*。這意味著妳需要向其傳遞的參數是char類型的字符串DWORD?WINAPI?GetModuleFileNameW(?HMODULE?hModule,?LPWSTR
lpFilename,?DWORD?nSize?);//UNICODE版本,第二個參數是LPWSTR,也就是wchar_t*。這意味著妳需要向其傳遞的參數是wchar_t類型的字符串。如果妳的代碼預定義了宏“UNICODE”,那麽在編譯時,“GetModuleFileName”就會被替換成“GetModuleFileNameW”,否則就是“GetModuleFileNameA”。
同理,_tcsrchr也是壹個宏,當預定義了“_UNICODE”宏時,它會在編譯時替換為
wchar_t?*wcsrchr(const?wchar_t?*str,
wchar_t?c?
);?//?C?only
因為凡是涉及字符串的函數,幾乎都有對應的ANSI和UNICODE版本,比如wcsrchr、strrchr、strcmp、wcscmp等等。在妳的代碼中對各個接口、函數的ANSI版本和UNICODE版本的使用應該始終保持壹致,以避免出現錯誤。
而妳的代碼,首先明確使用了ANSI版本的接口GetModuleFileNameA,而其後又將ANSI字符串提交給UNICODE版本的wcsrchr使用,所以會出現錯誤。
另:關於char和wchar_t的區別想必妳應該了解,wchar_t字符串中每壹個字符都由兩個字節組成,對於ascii表中的字符,都會在高位字節補0以補齊兩個字節。字符a其ascii碼為0x61,用char類型表示時其值為0x61,但是用wchar_t表示時,由於wchar_t為雙字符,因此其值應是0x0061——在INTEL x86和x64架構的系統中,字節序列表示就成了“0x61 0x00”。
比如有字符串"abcdefg",當妳用char類型表示這壹串字符串時,C代碼會這樣寫:
char?aString[]?=?{"abcdefg"};它在內存中的存在形式將是這樣的:
61 62 63 64 65 66 67 00 ; abcdefg.
如果用wchar_t去表示,C代碼如下:
wchar_t?wString[]?=?{L"abcdefg"};在內存中的存在形式就會變為這樣:
61 00 62 00 63 00 64 00 65 00 66 00 67 00 00 00 ; a.b.c.d.e.f.g...
由於每個字符都要雙字符表示,因此在此示例中wchar_t表示的字符串會多了壹半的0。當妳把wchar_t表示的字符串字節序列強行當作char*類型來處理時,就會出現意料之外的問題。
因此妳的代碼應該這樣寫:
TCHAR?tszCfgFile[MAX_PATH]={0};//TCHAR也是宏定義,當預定義了UNICODE時,等同於wchar_t,否則等於char。與GetModuleFileName的宏定義保持壹致。GetModuleFileName(?gDllModule,?tszCfgFile,?MAX_PATH);?
_tcsrchr(?tszCfgFile,?_T('\\')?)[1]?=?0;//這樣寫是危險的,如果tszCfgFile並不包含\\,此行將導致崩潰。