Am I converting properly from "const char *" to "TCHAR*"? - c++

I'm trying to pass a process name as a TCHAR to the following void:
void GetBaseAddressByName(DWORD pID, TCHAR *pN)
By doing it like this:
GetBaseAddressByName(aProcs[i], (TCHAR*)"Process.exe");
So my question is: is what I am doing correct? Because I have tried both TEXT("Process.exe") and _T("Process.exe") with my project's Character Set both on Multi-Bite and Unicode and it just tells me that
argument of type "const char*" is incompatible with parameter of type "TCHAR*"

The short answer is no. TCHAR maps to either char or wchar_t depending on your project's Unicode/Multi-byte setting. So, in general, a cast like that is either unnecessary or incorrect. The correct way, as you said, is to use either the TEXT or _T macro. The reason you're getting an error is that you're trying to pass a const character string to a function that expects a mutable character string. The safeset way to get around the error is to copy your constant string into a local TCHAR buffer and then pass that to GetBaseAddressByName.

It is better to have a TCHAR array first, then copy into it.
#include "atlstr.h"
char const * procName = "processName.exe";
TCHAR szName [128];
_tcscpy(szName, A2T(procName));
GetBaseAddressByName(aProcs[i], szName);
As suggested by #Remy Lebeau in the comments, procName can be defined as TCHAR const * procName = TEXT("processName.exe");.

(TCHAR*)"Process.exe" is not a valid type-cast. It will "work" when the project charset is set to ANSI/MBCS, but it will produce garbage if the charset is set to Unicode.
Using TEXT("Process.exe") is the correct way to make a string literal use TCHAR characters.
GetBaseAddressByName(aProcs[i], TEXT("Process.exe"));
However, you need to change your pN parameter to const TCHAR * (or LPCTSTR) instead:
void GetBaseAddressByName(DWORD pID, const TCHAR *pN);
void GetBaseAddressByName(DWORD pID, LPCTSTR pN);
A string literal is const data, and you cannot pass a pointer-to-const-data where a pointer-to-non-const-data is expected (without casting the const away with const_cast). That is why you were still getting errors when trying to use the TEXT()/_T() macros.

You need a L, like L"Process.exe". Unicode strings are specified with L"".
That said, there is no reason to use TCHAR. Use unicode all the time, if doing Windows work only.

Related

How to convert TCHAR to const char?

The most similar thing I found is conversion to char. I'm trying to convert TCHAR "path" to const char. Btw I use character set: "Not Set".
#include <stdlib.h>
// ... your defines
#define MAX_LEN 100
TCHAR *systemDrive = getenv("systemDrive");
TCHAR path[_MAX_PATH];
_tcscpy(path, systemDrive);
TCHAR c_wPath[MAX_LEN] = _T("Hello world!");//this is original
//TCHAR c_wPath[MAX_LEN] = path; "path" shows error
char c_szPath[MAX_LEN];
wcstombs(c_szPath, c_wPath, wcslen(c_wPath) + 1);
TCHAR is alias for different types depending of platform, defined macros, etc.
so, TCHAR can be alias for char(1 byte) or WCHAR(2 bytes).
further, WCHAR can be alias for wchar_t or unsigned short.
But, you made conversion using wcstombs which has signature like
size_t wcstombs(char *, const wchar_t *, size_t),
so you have
char* c_szPath
pointing to converted array of char,
now, if you need const char*, it is probably enough to write simply
const char * myPath = c_szPath, it is legal, and use myPath.
But maybe, you even don't need this, because char* can bind on argument of type
const char * if you need to pass it to function as argument.
When you say,
"path" shows error
that is because array type is not assignable.
I really hope this helps.

C++ Combine 2 Tchar

I'm trying to combine 2 tchar.
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
TCHAR* appdatapath ="C:\\Users\\"+username+"\\AppData";
But I get error error at appdatapath line. How can I combine 2 tchar? Thanks
Have a look at strcat and wcscat. You can't add char pointer with char array.
If you are on a windows machine, you can use _tcscat which will redirect to the right function to use depending on _UNICODE and _MBCS defines.
Might want to use the safe versions as well by appending _s to the function name.
As pointed in the comments, you can also use snprintf like so:
const size_t concatenated_size = 256;
char concatenated[concatenated_size];
snprintf(concatenated, concatenated_size, "C:\\Users\\%s\\AppData", username);
Since you have string literals before and after the runtime string, it is probably a better approach.
To answer the question in the title: you concatenate two TCHAR strings using the _tcscat function.
However, there are other issues in your code related to this: GetUserName expects a LPTSTR, i.e. a pointer to a buffer TCHAR characters. Furthermore, there's another TCHAR usage in
TCHAR* appdatapath ="C:\\Users\\"+username+"\\AppData";
The issue with this is that the type to which TCHAR expands changes depending on whether _UNICODE is defined. In particular, if you set it, TCHAR (eventually) expands to wchar and hence GetUserName expects a wchar_t* but you pass a char*. Another issue is that you cannot concatenate C arrays using the + operator.
I suggest to stop worrying about TCHAR in the first place and always just compile with _UNICODE defined - and use wchar throughout your code. Also, since you're using C++, just use std::wstring:
wchar username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserNameW(username, &username_len);
std::wstring appdatapath = L"C:\\Users\\";
appdatapath += username;
appdatapath += L"\\AppData";
Last but not least: your entire code can probably be replaced with a call to the SHGetSpecialFolderPath function - pass CSIDL_APPDATA to it to get the "AppData" path.
#include <tchar.h>
const size_t stringSize= 20;
TCHAR value[stringSize] = { 0 };
_tcscat_s(value, stringSize, TEXT("appendMe"));
MSDN: _tcscat_s

convert string to _T in cpp

I want to convert string or char* to the _T but not able to do.
if i write
_tcscpy(cmdline,_T ("hello world"));
it works perfectly, but if i write
char* msg="hello world";
_tcscpy(cmdline,_T (msg));
it shows an error like: error C2065: 'Lmsg' : undeclared identifier
Please give me a solution.
Thanx in advance.
_T is a macro, defined as (if UNICODE is defined):
#define _T(a) L ## a
which can work only with string-literals. So when you write _T("hi") it becomes L"hi" which is valid, as expected. But when you write _T(msg) it becomes Lmsg which is an undefined identifier, and you didn't intend that.
All you need is this function mbstowcs as:
const char* msg="hello world"; //use const char*, instead of char*
wchar_t *wmsg = new wchar_t[strlen(msg)+1]; //memory allocation
mbstowcs(wmsg, msg, strlen(msg)+1);
//then use wmsg instead of msg
_tcscpy(cmdline, wmsg);
//memory deallocation - must do to avoid memory leak!
delete []wmsg;
_T only works with string literals. All it does is turn the literal into an L"" string if the code's being compiled with Unicode support, or leave it alone otherwise.
Take a look at http://msdn.microsoft.com/en-us/library/dybsewaf(v=vs.80).aspx
You need to use mbtowcs function.
You should also look at this article.
_T is a macro that makes string literals into wide-char string literals by prepending an L before the literal in UNICODE builds.
In other words, when you write _T("Hello") it is as if you had written "Hello" on an ANSI build or L"Hello" on a UNICODE build. The type of the resulting expression is char* or wchar_t* respectively.
_T can not convert a string variable (std::string or char*) to a wchar_t* -- for this, you have to use a function like mbstowcs or MultiByteToWideChar.
Suggestion: It will be much easier for you (and in no way worse) to always make a UNICODE build and forget about _T, TCHAR and all other T-derivatives. Just use wide-character strings everywhere.
_T is not an actual type. It's a macro that prepends string literals with L so that they would be wchar_t*s instead of char*. If you need to convert a char* string to wchar_t* one at runtime, you need mbtowcs for example.
The _T modifier is just a declaration to tell the compiler that the string literal must be interpreted as a utf-16 encoding. The reason it doesn't work on the variable is because the contents of that variable have already been declared as ascii.
As already mentioned the mbstowcs function is what you need to perform the conversion of a char data into utf-16 (wide char) data.

Making TCHAR* compatible with char*

So a quick question how do I make TCHAR* (or wchar_t as its a macro) work with char*?
I am using the unicode character set.
The code that is the problem is:
TCHAR* D3DDevTypeToString(D3DDEVTYPE devType) {
switch (devType) {
case D3DDEVTYPE_HAL:
return TEXT("D3DDEVTYPE_HAL");
case D3DDEVTYPE_SW:
return TEXT("D3DDEVTYPE_SW");
case D3DDEVTYPE_REF:
return TEXT("D3DDEVTYPE_REF");
default:
return TEXT("Unknown devType");
}
}
The obvious solution is to change TCHAR* to char* but I would like to keep it as TCHAR* if possible.
Thanks.
And yes I am using the unicode character set.
Then you cannot make TCHAR compatible with char. Because if you're using UCS, then TCHAR is wchar_t. The type char is not related in any way to wchar_t. You could do some work to convert the string (using e.g. WideCharToMultiByte), but then you'd lose Unicode support.
TCHAR could be wchar_t or char, depeding upon whether the macro UNICODE is defined or not.
If the macro UNICODE is defined, then TCHAR means wchar_t. In this case, you cannot use TCHAR in place of, or with, char. It's dangerous!
If it's not defined, then TCHAR means char. In this case, you can use TCHAR in place of, or with, char. After all, they're same now.
Write a converter from UTF-16 to UTF-8 (or use the win32 API function if that's what it does). Make it generic so it can work on char*, wchar_t*, std::string, and std::wstring. Write a templated function string_cast and let the second parameter be figured out by the compiler. Override string_cast for the different combinations you will be using. Convert between TCHAR* to std::string with string_cast and then it doesn't matter how TCHAR is defined (assuming you overrode for both char and wchar_t.

How to convert tchar pointer to char pointer

I want to conver a tchar* to char * is this possible . if yes how to do it. I use unicode setting
A TCHAR is either a plain char or a wchar_t depending on your project's settings. If it's the latter, you would need to use WideCharToMultiByte with appropriate code page parameter.
You can't convert the pointer, you need to allocate a new string that is "char" instead of "wchar_t"
the most elegant way to do this is with the ATL conversion macros because it will hide all the allocation and called to the functions mentioned in the other comments
example
#include <atlbase.h>
#include <atlconv.h>
void YourFunction()
{
TCHAR wszHelloTchar = _T("Hello!\n");
USES_CONVERSION; // a macro required once before using T2A() and other ATL macros
// printf require a char*
// T2A converts (if necessary) the TCHAR string to char
printf( T2A( wszHelloTchar ) );
}
I find wcstombs works great for doing this sort of thing,