Cast CString to ANSI string in UNICODE projects
Quick Answer: use an intermediate CStringA.
- Normally, this is not something that should be done.
- It is technically unreliable, unless you can guarantee that the source CString to be converted does not contain any 2-byte characters.
- This will work fine if you are using the English language without any special 2-byte symbols or accented letters.
- This article is for educational use, and explains how it can easily be done, without relying on the USES_CONVERSION macro with W2A, or ridiculous WideCharToMultiByte API functions.
- If you are using a language that actually requires Unicode (Asian languages, etc), or if the CString contains any 2-byte character, this cannot be done. This is because there is no ANSI equivalent of any 2-byte character.
- It is the responsibility of the programmer to ensure that the CString does not contain any 2-byte characters.
Use intermediate CStringA:
- Recommended, simple, easy, effective, almost impossible to use improperly.
- This is only reliable if the CString does not contain any 2-byte characters.
CString LastNameW( L"Smith" ); CStringA LastNameA( LastNameW ); FunctionForAnsi( (LPCSTR)LastNameA );
- Or an even simpler example:
CString LastNameW( L"Smith" ); FunctionForAnsi( (LPCSTR)CStringA( LastNameW ) );
Here are some other ways that either do not work or are not recommended. I list them here to document things to avoid. What not to do.
WideCharToMultiByte API function:
- Not recommended, too much code to write, test, debug.
CString LastNameW( L"Smith" ); int nLen = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)LastNameW, -1, NULL, NULL ); LPSTR lpszA = new CHAR[nLen]; WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)LastNameW, -1, lpszA, nLen ); FunctionForAnsi( lpszA ); delete[] lpszA; // free the string
W2A ATL 3.0 macros:
- Not recommended, not safe inside loops.
USES_CONVERSION; CString LastNameW( L"Smith" ); FunctionForAnsi( W2A( (LPCWSTR)LastNameW ) );
CW2A ATL 7.0 conversion template classes:
- Not recommended, strict rules to follow for proper usage, too easy to use improperly.
CW2A: correct usage:
CString LastNameW( L"Smith" ); CW2A pszA( (LPCWSTR)LastNameW ); // this is the right way FunctionForAnsi( pszA );
CW2A: improper usage, do not do this
CString LastNameW( L"Smith" ); FunctionForAnsi( CW2A( (LPCWSTR)LastNameW ) ); // improper usage, do not do this
CW2A: improper usage, do not do this
CString LastNameW( L"Smith" ); LPCSTR pszA = CW2A( (LPCWSTR)LastNameW ); // improper usage, do not do this FunctionForAnsi( pszA );
(LPCSTR)(LPCTSTR) cast:
- Does not work.
- You cannot simply use (LPCSTR)(LPCTSTR) to cast a CString to LPCSTR in Unicode projects.
- It does compile, but it does not properly convert the CStringW to an LPCSTR.
- The resulting string will either be 0 or 1 length, or filled with garbage characters of unknown length, because the cast just changes the pointer type without any conversion.
- You end up with a CHAR* pointing to a WCHAR array, a very bad thing.
CString LastName( L"Smith" ); FunctionForAnsi( (LPCSTR)(LPCTSTR)LastName ); // does not work
REF:
ATL String: What’s wrong with the USES_CONVERSION macros? How to avoid using them?
Posted on January 3, 2012, in C/C++, MFC and tagged ANSI, cast, char*, CString, CStringA, LPCSTR, LPCTSTR, LPCWSTR, TCHAR, unicode, USES_CONVERSION, W2A, WCHAR, WideCharToMultiByte. Bookmark the permalink. Leave a Comment.
Leave a Comment
Comments (0)