A Friendly Piece of Advice: The TCHAR Model? Forget About It!

I believe modern Windows Win32/C++ applications should just use Unicode builds, instead of the obsolete TCHAR model.

For example, consider some Win32/C++ code like this:

CString str;
TCHAR* buf = str.GetBuffer(maxLength);
// Write something in buf ...
buf[n] = L'\0'; // (1)
str.ReleaseBuffer();

// Other code ...

TCHAR * text = /* some valid output buffer */;
swprintf_s(text, L"Something ...", ...); // (2)

// DoSomething() is declared as:
//
//   void DoSomething(const wchar_t* psz);
//
DoSomething(text); // (3)

The author of that piece of code thinks he followed the TCHAR model, probably because he used TCHAR throughout his code; but he’s wrong. For example:

  1. If buf is a TCHAR*, the correct TCHAR-model assignment should be “buf[n] = _T(‘\0’);”, i.e. use the _T or TEXT preprocessor macros instead of the L prefix.
  2. swprintf_s should be substituted with _stprintf_s, and again the L prefix should be substituted with the _T or TEXT preprocessor macros.
  3. The TCHAR string “text” should be converted to a wchar_t string before passing it to the DoSomething function, e.g. using an ATL helper like CT2W or CT2CW (e.g. “DoSomething(CT2W(text));”).

So, following the TCHAR model would actually make the code more complicated. And for what?

For being able to compile the same source code also in ANSI/MBCS? And is the whole code base properly tested for ANSI/MBCS builds? And in case of ANSI/MBCS builds, what code page(s) is(are) used for char-based strings? Are the conversions from those code pages to Unicode done properly? This can be a bug factory! And, do you (or your clients) really need an ANSI/MBCS build of your software??

So, in my opinion, the best thing to do in modern Win32 C++ applications is to just forget about the TCHAR model, and to just use Unicode UTF-16 at least at the Win32 API boundary, and just use WCHAR or wchar_t instead of TCHAR (in other words: assume that TCHAR is wchar_t), and assume that Win32 APIs that take TCHAR-strings (e.g. SetWindowText) just take Unicode UTF-16 wchar_t-strings.

In other words: Just assume Unicode builds for Win32 C++ code.

I’d rewrite the above code fragment simply assuming that TCHAR is wchar_t, like this:

CString str;
// CString stores Unicode UTF-16 text 
// in Unicode builds
wchar_t* buf = str.GetBuffer(maxLength);

// Write something in buf ...
buf[n] = L'\0';
str.ReleaseBuffer();

// Other code ...

wchar_t * text = /* some valid output buffer */;
swprintf_s(text, L"Something ...", ...);

// DoSomething() is declared as:
//
//   void DoSomething(const wchar_t* psz);
//
DoSomething(text);

It’s also interesting to point out that some “modern” (e.g. Vista+) Windows APIs like DrawThemeTextEx just take Unicode (UTF-16) strings; i.e. the pszText parameter of the aforementioned API is of type LPCWSTR, i.e. “const WCHAR*” (instead of LPCTSTR, i.e. “const TCHAR*”).

 

One Reply to “A Friendly Piece of Advice: The TCHAR Model? Forget About It!”

Leave a Reply

Your email address will not be published. Required fields are marked *