Errors using TCHAR,cannot convert to wchar_t

yiannis picture yiannis · Jan 21, 2014 · Viewed 13.4k times · Source

I've been asked to add functionality to an existing old project but i cannot get it to build. It handles unicode strings but i get a lot of errors regarding the use of TCHAR.Specifically almost every error is TCHAR cannot be converted to or used as wchar_t. From what i saw on many different articles i tried using #define _UNICODE or #define UNICODE but none of them solved the problem.

Here is a piece of the code:

#include <windows.h>
#include <wininet.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <strsafe.h>
#include <string>
#include <list>
#include <cctype>
#include <winnt.h>
#include <atlconv.h>

#pragma comment(lib,"wininet.lib")

using namespace std;

TCHAR *tags[] = { _T("aa"), _T("bb"), _T("cc"),
NULL };

int _tmain(int argc, _TCHAR* argv[])
{


int i = 0;


for (i = 1; i<argc; i++) { 
    if (wcscmp(argv[i], _T("-h")) == 0) {
        ...
    }
    else if (wcscmp(argv[i], _T("-f")) == 0) {
        ...
    }


...
}

In the above lines for example,when using wcscmp, i get

    argument of type "_TCHAR *" is incompatible with parameter of type "const wchar_t *"

regarding the argv[i]

and

    argument of type "const char *" is incompatible with parameter of type "const wchar_t *"

regarding the _T("-h").

Any suggestions would be really appreciated.

Answer

David Heffernan picture David Heffernan · Jan 21, 2014

The code has been written to target Unicode rather than MBCS. This can be discerned by the use of wcscmp which accepts parameters of type const wchar_t*.

On the other hand, there are parts of the code which use TCHAR and related macros. Now, TCHAR is a macro that resolves to either char or wchar_t depending on whether or not _UNICODE or _MBCS are defined. Consult the documentation for more details.

The use of TCHAR stems from the days when developers wished to write code for both Windows NT/2000 (which supported both ANSI and Unicode APIs), and Windows 95/98 (which has only ANSI APIs). The use of TCHAR allowed a common code base. Compile with _UNICODE defined for NT/2000, and compile with _MBCS defined for 95/98.

If you code in this style then you write _tcscmp rather than wcscmp. For a Unicode build it resolves wcscmp, and for an MBCS build it resolves to _mbscmp.

These days you typically do not need to write code to support 95/98. You can probably choose to neglect those platforms. In which case you should target Unicode and stop using TCHAR and related macros. Replace _T("..") with L"..". Replace tmain with wmain. Replace TCHAR with wchar_t. And so on.

You don't need to make these changes. You could simply target Unicode and your code will compile. However, the TCHAR idiom has been applied inconsistently in your code base. Note the use of _tmain, TCHAR, but also the calls to wcscmp. So your code cannot compile unless it targets Unicode. So you are losing nothing by abandoning TCHAR. What you gain is clarity. You get to stop using these macros and avoid all the obfuscation that they provide. Indirection is a great tool, but if it is not needed then it simply leads to confusion and obfuscation.