You are here:

C++/char* versus _TCHAR

Advertisement


Question
Hi Ralph,

Many thanks for your informative email. Very interesting,
I promise to rate you well for your trouble.
One thing i want to ask, i also saw something like this in a program.

TCHAR* names[4] =
{
 _T("Anne"),
 _T("Barry"),
 _T("Conor"),
 _T("Dave")
};


If i wanted to pass this array to a function called eg.

people.SetNames(numPeople, names)

How do i pass the 'names' parameter,
i tried *names, *names[4] etc, but the compiler doesnt like it.

I guess i am just wondering what is the correct procedure to pass an
array of strings. Its not easy.

Also, can i use strcpy for _TCHAR* or will strcpy not like _TCHAR*
as its not a char*

Best Regards,
Cruiser




-------------------------
Followup To
Question -
Hi Ralph,
Just wondering what is the difference between _TCHAR* and char*? I saw an array of names in a program defined as type _TCHAR. Can one use char* instead as in: char* names = {
 _T("Anne"),
 _T("Barry"),
 _T("Conor"),
 _T("Dave")
};

This was originally defined as _TCHAR*.
Is _TCHAR just merely putting a tab for spacing
purposes in the array? Or am i wrong with this assumption?

Many thanks,
Cruiser
Answer -
Yes you are wrong in your assumption. It has nothing to do with the text itself.

It has to do with the character type. C and C++ have 2 character types: char and wchar_t. In C wchar_t is a typedef to some integer type. In C++ it is a built in type. char is used for narrow characters and is typically an 8-bit type. wchar_t however is for wide characters and is typically a 16-bit or greater sized integer type.

The Microsoft Win32 operating system API has many API functions that exist in two versions: narrow 8-bit ANSI character and string functions and wide, 16-bit, UNICODE character and string functions. ANSI function names end in A and UNICODE function names end in W. For example:

       WriteConsoleOutputA and WriteConsoleOutputW

The Win32 SDK header files define macros for each such function pair that does not have the A or W at the end, WriteConsoleOutput for example. Whether these macros map to the A or W version of the API functions depends on whether you are building the application for use with 8-bit ANSI characters or 16-bit wide, UNICODE characters.

Now the problem comes when you wish to pass text to these functions - the types change depending on how the application is built - char or wchar_t. This is where _TCHAR come in as well as _T - these are typedefs and macros. _TCHAR is a typedef type alias to the underlying Win32 API character set character type - char or wchar_t (or possibly unsigned short, it seems to vary depending on which SDK headers you are using). _T is a macro,_T(x) expands to x for ANSI character builds and L ## x for UNICODE builds - so _T("hi") is either "hi" for ANSI builds or L"hi" - a wide char string literal - for UNICODE builds. So in your example code above as you are using _T then the character type should be based on _TCHAR and not char (or wchar_t for that matter). So you should use something like:

TCHAR* names =
{
 _T("Anne"),
 _T("Barry"),
 _T("Conor"),
 _T("Dave")
};

The reason is that using char (or in this case char*) is _only_ OK so long as you are _not_ building using UNICODE as the character set.

As a point of interest Microsoft also have a various other _T or _t or prefixed names - _tmain for example is defined to be either main or the Microsoft specific extension for UNICODE applications, wmain. The tchar.h header file also contains a load of _t prefixed functions mapping onto the C library string functions such as _tcsclen mapping onto either strlen or wcslen, the wide character equivalent. Some of these map to non standard and/or MS specific functions - particularly for the multi byte character support functions (multi byte characters are used to get more characters out of single byte characters string - i.e. char based strings. To achieve this some character consist of more than one character - so the number of chars used to store the string may be different from the number of characters in the string.)  

Answer
names is an array of four pointers to _TCHAR so you pass it as names. However you do have to get the type correct in the function declaration.

       people.SetNames(numPeople, names)

Does not tell the whole story does it?

What is needed is the declaration of SetNames which I would expect to be in the class definition for the type of object people neither of which you show.

You can declare the people's names parameter to SetNames to be an array of four _TCHAR*:

       void SetNames( size_t numPeople, _TCHAR * names[4] );

And then pass names in directly into the function as shown above:

       people.SetNames(numPeople, names)

However, this means you can only pass arrays of 4 names at a time making the numPeople parameter redundant. So, as is common in C and C++ , pass the array as a pointer instead:

       void SetNames( size_t numPeople, _TCHAR ** names );

You end up needing 2 *'s as the array contains pointers to start with:
- the first *, as in the previous version, as the array contains _TCHAR *
- the second because we are passing a pointer to the first element - a _TCHAR * .

Array types convert to a pointer to the first element easily enough in C and C++. However doing so of course looses the array dimension information hence your need for the numPeople parameter.

Now as to strcpy as with the previous answer it only works if you are building as char / ANSI projects without multi byte character support, not a UNICODE project when _TCHAR would be a wchar_t and you would have to use wcscpy instead (or using multi byte characters when you could use the MS specific _mbscpy).

As I mentioned there are many _t named items for handling _TCHARs to switch between the various underlying function in this case the macro is called _tcscpy. You can find other such macros listed in tchar.h part of the MSVC++ runtime library so search your system for this header. They are also documented in the MSDN library usually the char, wchar_t, char using multi byte character sets, and _TCHAR versions are all documented together so looking for the MSDN library documentation for strcpy should point you at the other functions (or macros that are intended to be used in their place). You can find this documentation online at http://www.msdn.microsoft.com/. This assumes you are using a MS compiler and its runtime library. You will note that you can also build your project for multi byte characters and _TCHAR and _tcscpy et al will map to the correct types and functions. An note in tchar.h points out that for the strcpy case _mbscpy is equivalent to strcpy.

Please look in the MSDN library documentation for other related _t 'functions'.

Of course if you are not bothered about different build using character types then do not use _TCHAR, _T and _t functions at all. But which ever way you go, do things consistently. If you are using _TCHAR and _T use the _t functions. If not then use the standard C library functions and any available vendor extensions (if you do not care about portability), for char and wchar_t string handling.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.