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?

Using MFC MBCS/Unicode Conversion Macros

ATL and MFC String Conversion Macros

About these ads

About Ed Nafziger

Ed is a computer programmer who works on both MFC/C projects and maintaining legacy C code. The majority of projects he works with are either Windows desktop or CE, and he will be sharing some of his trade secrets on these topics.

Posted on January 3, 2012, in C/C++, MFC and tagged , , , , , , , , , , , , , . Bookmark the permalink. Leave a Comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: