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; char sUsername[64];
with
wchar_t cResponse; wchar_t sUsername[64];
You can simply code it:
#include<TCHAR.H> // Implicit or explicit include
TCHAR cResponse; TCHAR sUsername[64];
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"; L"Unicode String";
_T("Either string, depending on compilation");
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?
foo_ansi(char*);
foo_ansi(const char*);
char* pString;
foo_uni(WCHAR*); foo_uni(const WCHAR*);
WCHAR* pString;
foo_char(TCHAR*);
foo_char(const TCHAR*);
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

:
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];
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;
pBuffer = new TCHAR[128];
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.