The Unreadable Obscure LPXYSTR Typedefs

If you write Win32 C++ code, you’ll find a lot of unreadable and apparently obscure typedefs for strings, for example: LPCTSTR, LPTSTR, LPCWSTR, etc.

What are those? What do they mean?

The key to understand those apparently obscure (but certainly unreadable!) typedefs is to split their names into smaller parts.

Let’s start with the “decoding” of LPCTSTR:

  • LP means pointer. I think it actually means something like “long pointer”, in a period (16-bit Windows?) when probably there were both “long” (far?) and “short” (near?) pointers, but this predates my experience with the C++ Windows platform, so I just don’t know for sure.
  • C means: const, constant.
  • T means: TCHAR
  • STR means: C-style NUL-terminated string.

So, putting those elements together, an “LPCTSTR” is a “pointer to a read-only (const) NUL-terminated TCHAR string”, i.e. in C and C++ code: “const TCHAR*. You can find LPCTSTR parameters in many Win32 APIs, e.g. in SetWindowText.

Now, to be honest, to me “const TCHAR*” is much more readable than “LPCTSTR”: In fact, using the former, I can clearly see all the composing elements: “const”, “TCHAR”, “pointer”. Instead, in the latter “LPCTSTR” compressed form, the components are zipped together in an obscure unreadable form.

Since I gave a friendly piece of advice to forget about the TCHAR model, let’s substitute “TCHAR” with “wchar_t” in Unicode builds, so LPCTSTR becomes “const wchar_t*”! So, we get basically a pointer to a read-only C-style NUL-terminated Unicode (UTF-16) string.

Let’s do another one: LPTSTR.

  • LP: pointer
  • T: TCHAR
  • STR: NUL-terminated string

So, this is basically like LPCTSTR, but missing the “C” (“const”). So, this is a string buffer that isn’t read-only: you can write into it; for example, think of the output string returned by GetWindowText.

In code, it’s: “TCHAR *”, which is equivalent to “wchar_t*” in Unicode builds. Let’s see: “wchar_t*” vs. “LPTSTR”. Wow! The former (“wchar_t*”) is much simpler and more readable to me!

And let’s be honest that the difference between LPCTSTR and LPTSTR is very subtle: the “C” for “const” is buried in the middle of the LPCTSTR typedef! Instead, the difference between “const wchar_t*” and “wchar_t*” is much more clear!

Finally, let’s analyze LPCWSTR.

  • LP: pointer
  • C: const
  • W: wide, i.e. WCHAR/wchar_t based
  • STR: NUL-terminated string

So, this a pointer to a read-only (const) wchar_t-based (i.e. Unicode UTF-16) NUL-terminated string; in C++ code that translates to “const wchar_t*”. Again, in my opinion the expanded form is much more readable than the obscure “LPCWSTR” typedef. You can find this typedef used e.g. in the DrawThemeTextEx Win32 API.

Let’s summarize these results in a nice table:

Win32 Obscure Typedef Expanded Equivalent Equivalent in Unicode Builds
LPCTSTR const TCHAR * const wchar_t*
LPTSTR TCHAR * wchar_t*
LPCWSTR const wchar_t* const wchar_t*

Decoding other obscure Win32 typedefs is left as an Exercise for The Reader (TM). Actually, I hope those typedefs will now be a little bit less obscure…

Note also that you may find the pointer part sometimes abbreviated using “P” instead of “LP”: Welcome to the New World of (just) pointers, without long/short/near/far pointers 🙂

And, as a coding style, I think that using the underlying C++ types (like in “const wchar_t*”) is much better (e.g. clearer, less bug-prone) than using those Win32 typedefs (like “PCWSTR”).


One Reply to “The Unreadable Obscure LPXYSTR Typedefs”

Leave a Reply

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