16

I am having crazy difficulty understanding and getting this to work properly. Basically what it comes down to is that I cannot successfully initialize a variable of this type. It needs to have the contents of say 7&2E25DC9D&0&USB003.

Can anybody please explain/show a proper initialization of this type w/ a similar value? I have looked at all the help on this site and changing my project properties from unicode to multibyte is not solving the issue, and the other solutions aren't working for me either.

As my code sits, here is how I am starting the initialization:

LPCTSTR portvalue = new TCHAR[100];
genpfault
  • 51,148
  • 11
  • 85
  • 139
N3rdB0mber
  • 141
  • 1
  • 1
  • 6
  • 2
    I'd recommend sticking to `std::wstring`. – chris Jul 19 '13 at 19:02
  • 3
    Or, abandon `LPCTSTR`, and simply use `CStringW` or `std::wstring`. – Mooing Duck Jul 19 '13 at 19:06
  • 2
    AFAICT, the only reason to support both "Unicode" and "multibyte"/"ASCII" encodings is if you want your code to run on Windows 3.0. If your code only runs on WindowsNT3.1 and newer, it's easier to just assume `_UNICODE` is true and use wstring everywhere. – Mooing Duck Jul 19 '13 at 19:28
  • @MooingDuck On that point Multibyte support in MFC is actually deprecated in Microsoft Visual Studio 2013 and onwards. – Thomas Russell Jul 19 '13 at 19:31

2 Answers2

26

As you seem to have gathered, LPCTSTR and TCHAR are basically defined as following (LPCTSTR would be read long pointer to constant TCHAR):

#ifdef _UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif // _UNICODE

typedef const TCHAR* LPCTSTR;

So you can initialize a LPCTSTR variable as you would a const wchar_t* or a const char* variable, e.g. for unicode:

LPCTSTR lpszUnicode = L"Test String";

And for ASCII/MultiByte:

LPCTSTR lpszMultibyte = "Test String";

There are however, useful macros when working with the WinAPI: _T("x") and TEXT("x"), which both expand to L"x" (if your project is set for Unicode) or "x" (if your project properties are set for Multibyte). So for instance, you could use:

LPCTSTR lpszTest = _T("Test String");
LPCTSTR lpszTest2 = TEXT("Test String 2");

And this will compile under either unicode or multibyte project settings. As for the reason that there are multiple macros expanding to the same thing, check out this blog post.


You can also do what you are doing by dynamically allocating memory as you have done, so for instance:

LPTSTR lpszDynamic = new TCHAR[100];
// Do something with lpszDynamic
delete[] lpszDynamic;

However, if you are finding yourself dynamically allocating memory often like this, it might be better to use string classes, such as CString or std::string/std::wstring (I often have the following in my MFC/WinAPI projects):

namespace std {
#ifdef _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif // _UNICODE
};
Thomas Russell
  • 5,870
  • 4
  • 33
  • 68
  • I'm pretty sure it's `UNICODE` for the winapi stuff, you can't add things to `std`, and you can just do `typedef std::basic_string tstring;`, but it's still a bad idea since `std::to_string` and stuff like that won't work. I just use `std::wstring` and forget about supporting operating systems from way back. – chris Jul 19 '13 at 19:33
  • @chris I just have a bunch of `typedef`d and `#define`d stuff which includes `std::to_string` (as `std::to_tstring`), etc. But yes, you're probably right that it isn't necessary. – Thomas Russell Jul 19 '13 at 19:33
  • Believe me, I've tried it (you can see some pretty horrid code in questions I've asked on here), and it really wasn't worth it at all. – chris Jul 19 '13 at 19:35
  • By the way, [this page](http://msdn.microsoft.com/en-us/library/windows/desktop/dd374131(v=vs.85).aspx) says `UNICODE`. – chris Jul 19 '13 at 19:36
13

From this answer, you have to prefix the literal with L

LPCWSTR a = L"TestWindow";

As Frederic pointed out, you can initialize a LPCTSTR in this manner:

LPCTSTR s = _T("TestWindow");
Community
  • 1
  • 1
Cory Klein
  • 51,188
  • 43
  • 183
  • 243