Click here to Skip to main content

What are TCHAR, WCHAR, LPSTR, LPWSTR, LPCTSTR (etc.)?

Many Windows C++ programmers get confused over what bizarre data type identifiers like TCHAR and LPCTSTR are. Here, in brief, I will try to clear out the fog.
Sign Up to vote bad good
Add a reason or comment to your vote: x
Votes of 3 or less require a comment
See more: C++Win32
Many C++ Windows programmers get confused over what bizarre identifiers like TCHAR, LPCTSTR are. Here, in brief, I would try to clear out the fog.
 
In general, a character can be 1 byte or 2 bytes. Let's say 1-byte character is ANSI, using which English characters are represented. And let's say 2-byte character is Unicode, which can represent ALL languages in the world.
 
VC++ support char and wchar_t as native datatypes for ANSI and Unicode characters respectively.
 
What if you want your C/C++ program to be Character-mode independent?
Use generic characters. That means, instead of replacing:
char cResponse; // 'Y' or 'N'
char sUsername[64];
// str* functions
with
wchar_t cResponse; // 'Y' or 'N'
wchar_t sUsername[64];
// wcs* functions
 
You can simply code it:
#include<TCHAR.H> // Implicit or explicit include
TCHAR cResponse; // 'Y' or 'N'
TCHAR sUsername[64];
// _tcs* functions
Thus, when your project is being compiled as Unicode, the TCHAR would translate to wchar_t. If it is being compiled as ANSI/MBCS, it would be translated to char. Likewise, instead of using strcpy, strlen, strcat (including the secure versions suffixed with _s); or wcscpy, wcslen, wcscat (including secure), you can simply use _tcscpy, _tcslen, _tcscat functions.
 
When you need to express hard-coded string, you can use:
"ANSI String"; // ANSI
L"Unicode String"; // Unicode

_T("Either string, depending on compilation"); // ANSI or Unicode
// or use TEXT macro, if you need more readability.
 
The non-prefixed string is ANSI string, the L prefixed string is Unicode, and string specified in _T or TEXT would be either, depending on compilation.
 
String classes, like MFC/ATL's CString implement two versions using macro. There are two classes named CStringA for ANSI, CStringW for Unicode. When you use CString (which is a macro/typedef), it translates to either of two classes.
Okay. The TCHAR type-definition was for a single character. You can definitely declare an array of TCHAR.
What if you want to express a character-pointer, or a const-character-pointer - Which one of the following?
// ANSI characters
foo_ansi(char*);
foo_ansi(const char*);
/*const*/ char* pString;
 
// Unicode/wide-string
foo_uni(WCHAR*); // or wchar_t*
foo_uni(const WCHAR*);
/*const*/ WCHAR* pString;
 
// Independent 
foo_char(TCHAR*);
foo_char(const TCHAR*);
/*const*/ TCHAR* pString;
After reading about TCHAR stuff, you'd definitely select the last one as your choice. But here is a better alternative. Before that, note that TCHAR.H header file declares only TCHAR datatype and for the following stuff, you need to include Windows.h (defined in WinNT.h).
 
NOTE: If your project implicitly or explicitly includes Windows.h, you need not include TCHAR.H
 
  • char* replacement: LPSTR
  • const char* replacement: LPCSTR
  • WCHAR* replacement: LPWSTR
  • const WCHAR* replacement: LPCWSTR (C before W, since const is before WCHAR)
  • TCHAR* replacement: LPTSTR
  • const TCHAR* replacement: LPCTSTR
Now, I hope you understand the following signatures Cool | :cool: :
BOOL SetCurrentDirectory( LPCTSTR lpPathName );
DWORD GetCurrentDirectory(DWORD nBufferLength,LPTSTR lpBuffer);
Continuing. You must have seen some functions/methods asking you to pass number of characters, or returning the number of characters. Well, like GetCurrentDirectory, you need to pass number of characters, and not number of bytes. For example::
TCHAR sCurrentDir[255];
 
// Pass 255 and not 255*2 
GetCurrentDirectory(sCurrentDir, 255);
On the other side, if you need to allocate number or characters, you must allocate proper number of bytes. In C++, you can simply use new:
LPTSTR pBuffer; // TCHAR* 

pBuffer = new TCHAR[128]; // Allocates 128 or 256 BYTES, depending on compilation.
But if you use memory allocation functions like malloc, LocalAlloc, GlobalAlloc, etc; you must specify the number of bytes!
pBuffer = (TCHAR*) malloc (128 * sizeof(TCHAR) );
Typecasting the return value is required, as you know. The expression in malloc's argument ensures that it allocates desired number of bytes - and makes up room for desired number of characters.
Posted 27 Apr '10
Edited 5 Feb '12

Comments
RajaManikandan_R - 22 Sep '10
Reason for my vote of 3 Nice explanation on TCHAR. How about adding BSTR, ComBSTR ?
Ajay Vijayvargiya - 22 Sep '10
I believe they are not common among Windows and/or MFC programmers. Thus, I have not added it. Also, putting them would require this Tip/Trick to be longer (Article would fit). I also believe that anyone using BSTR/ComBSTR knows well about ANSI/Unicode stuff.
tcljg2008 - 17 Dec '10
Reason for my vote of 4 very good
hervebags - 4 Jan '11
Reason for my vote of 4 Good introduction but, not easy enough to follow for a complete beginner.
goldenrose9 - 5 Jan '11
good article, but please expand its details. It will be very helpful for beginners, its a request
CompUser - 12 Jan '11
Reason for my vote of 5 Very clear and concise. Thank you!
iampradeepsharma - 8 Jun '11
very helpful article .
Bayram AKGÜL - 11 Jun '11
This was exactly my savior. thanks a lot
JeremyLanger - 27 Jun '11
Reason for my vote of 5 TCHAR szResponse[128] = _T("AWESOME ARTICLE. I learned a lot from it! Great job!");
GBSC - 1 Jul '11
Reason for my vote of 5 The explanation really cleared a lot of confusion as far as windows programming goes.
spawncxy - 26 Jul '11
Reason for my vote of 5 nice explanation!
Jose David Pujo - 25 Aug '11
Reason for my vote of 5 Good summary!
mtapiero - 13 Oct '11
Reason for my vote of 5 I'm starting with C for Windows, and was just struggling with these data types. Thanks a lot!
Pranit Kothari - 20 Dec '11
Reason for my vote of 5 Great work.!! I just request you to add some BSTR like stuff as well. But This is very good.
nv3 - 17 Jan '12
Reason for my vote of 4 Nice job, Ajay. Perhaps you should also mention PCTSTR ..., the variants without the "L" prefix. The L-names still come from the old times when we had multiple memory models and there were "large" pointers. Also, I would suggest explaining what happens when you initialize a CString with the "wrong" type of constant, namely an automatic conversion at runtime. An interesting side comment might be to explain the TRACE macro of MFC that also allows boths types of character constants.
sheniss - 23 Jan '12
Good one!
Boffin_Boy - 24 Jan '12
Reason for my vote of 4. The article lacks clarity and accuracy. There are Windows data types. Their complete list is here: http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx. Data types TCHAR, LPTSTR, LPCTSTR intended for use in Win32 API functions (GetSysytemInfo, GetVersionEx, etc.). TCHAR is a generic data type. After compiling it is converted into a char or wchar type. To use TCHAR you need a few things. The program begins with the line #include <windows.h> If you plan to use the generic string functions (_tprintf, _tcscat, _tcslen et al.), add #include <tchar.h> after the previous one. Main function have to be _tmain(). Then if you want to get a program with Unicode characters put #define UNICODE at the beginning (before the #include <windows.h>), if with ANSI symbols – put nothing. That’s all.
Saint Atique - 28 Jan '12
Reason for my vote of 5 Nice article on basic data types.
Member 7834206 - 7 Feb '12
Reason for my vote of 5 very good, short and clear

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Your Filters
Interested
Ignored
     
  1. SAKryukov (583)
  2. CRDave1988 (390)
  3. CPallini (315)
  4. Varun Sareen (308)
  1. SAKryukov (13,971)
  2. OriginalGriff (8,238)
  3. Christian Graus (7,396)
  4. thatraja (5,300)
  5. Abhinav S (5,103)

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralGood One PinmemberMANISH RASTOGI19:37 7 Feb '12  
GeneralRegarding CString and Unicode Pinmember aphazel 死神11:53 26 May '10  
GeneralRe: Regarding CString and Unicode PinmemberAjay Vijayvargiya17:51 26 May '10  
GeneralRe: Regarding CString and Unicode Pinmember aphazel 死神11:28 27 May '10  
GeneralRe: Regarding CString and Unicode PinmemberAlbert Holguin15:47 17 Jan '12  
Generalthanks Pinmembercute_friend70770:37 24 May '10  
GeneralSome notes Pinmemberxanatos22:53 27 Apr '10  
GeneralRe: Some notes PinmemberAjay Vijayvargiya6:46 1 May '10  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.


Advertise | Privacy | Mobile
Web04 | 2.5.120222.1 | Last Updated 5 Feb 2012
Copyright © CodeProject, 1999-2012
All Rights Reserved. Terms of Use
Layout: fixed | fluid