VC 字符串相關宏 _TTEXT,_TEXTL 的作用

一、 在字符串前加一個L作用:

    L"我的字符串"    表示將ANSI字符串轉換成unicode的字符串,就是每個字符占用兩個字節。

 strlen("asd")   =   3;  

 strlen(L"asd")   =   6;

 

二、 _T宏可以把一個引號引起來的字符串,根據你的環境設置,使得編譯器會根據編譯目標環境選擇合適的(Unicode還是ANSI)字符處理方式

   如果你定義了UNICODE,那么_T宏會把字符串前面加一個L。這時 _T("ABCD") 相當于 L"ABCD" ,這是寬字符串。

   如果沒有定義,那么_T宏不會在字符串前面加那個L_T("ABCD") 就等價于 "ABCD"

 

三、TEXT,_TEXT _T 一樣的

 

如下面三語句:  

 TCHAR   szStr1[]   =   TEXT("str1");  

 char   szStr2[]   =   "str2";  

 WCHAR   szStr3[]   =   L("str3");  

 那么第一句話在定義了UNICODE時會解釋為第三句話,沒有定義時就等于第二句話。 

 但二句話無論是否定義了UNICODE都是生成一個ANSI字符串,而第三句話總是生成UNICODE字符串。  

 為了程序的可移植性,建議都用第一種表示方法。  

 但在某些情況下,某個字符必須為ANSIUNICODE,那就用后兩種方法。

 

 

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. Lets say 1-byte character is ANSI, using which English characters are represented. And lets 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?
That means, instead of replacing:

Collapse | Copy Code

char cResponse; // 'Y' or 'N'
char sUsername[64];
// str* functions

with

Collapse | Copy Code

wchar_t cResponse; // 'Y' or 'N'
wchar_t sUsername[64];
// wcs* functions

You can simply code it:

Collapse | Copy Code

#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 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:

Collapse | Copy Code

"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 version 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?

Collapse | Copy Code

// 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 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 to 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 :

Collapse | Copy Code

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::

Collapse | Copy Code

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:

Collapse | Copy Code

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!

Collapse | Copy Code

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.

1