5

I am sort of new to C++ and I got troubles understanding the usage of the data types fully.

I have these variables to be applied to createwindow parameters and the class with it. That takes an LPCWSTR data type.

LPCWSTR szTitle = L"Hello";
LPCWSTR szWindowClass = L"There";

Therefore I did that, although, I don't understand why I have to include the L before the string (the debugger put it there to be honest). I have also not too often seen strings be defined as the direct types (instead I often see WCHAR,char, etc). If you would make these variables, how would you write them? I don't believe I should be using LPCWSTR. Again sorry, I am fairly new and I can't find exactly what I'm looking for online.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
JohnSilver
  • 83
  • 1
  • 3
  • 10
  • 4
    The short answer is: it's because you're using Microsoft Windows. This insanity is rarely seen in Linux, or pretty much anywhere else... – Sam Varshavchik Mar 15 '17 at 17:46
  • 3
    You should probably _drop that Windows-ish insanity_ and learn plain standard C++ first. – ForceBru Mar 15 '17 at 17:47
  • Windows-ish insanity? Can you elaborate please? – JohnSilver Mar 15 '17 at 17:49
  • What's with big corporations disregarding standards... It's not even for the better when you look at Windows... – DeiDei Mar 15 '17 at 17:49
  • 6
    Or.... learn/use whatever the heck you want and don't be put off by the non-Windows guys. See here for the Microsoft C++ compiler specifics related to this subject. https://msdn.microsoft.com/en-us/library/69ze775t.aspx – Inisheer Mar 15 '17 at 17:49
  • Is this not similar to [What exactly is the L prefix in C++?](http://stackoverflow.com/questions/13087219/what-exactly-is-the-l-prefix-in-c) – chickity china chinese chicken Mar 15 '17 at 17:50
  • 2
    @JohnSilver, this stuff is non-standard, so, if you try to move to Linux (or some UNIX-like platform), you'll spend hours dealing with lots of errors and finally end up with _standard C++_ code. And when you try to compile standard C++ on Windows... it'll be just fine and it'll also look _much_ cleaner. – ForceBru Mar 15 '17 at 17:55
  • You guys are saying I should define it as const wchar_t* (standard) instead of LPCWSTR (non-standard)? – JohnSilver Mar 15 '17 at 17:58
  • FIY, the reference web on wich the C++ community mostly agrees is http://en.cppreference.com/w/ Check out [`wchar_t` here](http://en.cppreference.com/w/cpp/language/types). – kebs Mar 15 '17 at 18:00
  • I would avoid defining it as `const wchar_t*` as that itself can change based on the [`/Zc:wchar_t`](https://msdn.microsoft.com/en-us/library/dh8che7s.aspx) flag. Using the macro will prevent errors. – lcs Mar 15 '17 at 18:02
  • @ForceBru there's nothing non-standard about using a proprietary header file. LPCWSTR? That's just a #define. L"string" ? A C++ standard wide-string literal. Hungarian notation? Just a standard-compliant convention. Agreed, it all looks ugly and inadvisable, but not non-standard. Posix has headers that are not part of the standard just like Windows has. – Klitos Kyriacou Mar 15 '17 at 18:03

2 Answers2

6

C++ has several different character types, and the ones at issue here are char and wchar_t, with wchar_t being a wide character of some implementation-defined type. A string literal in C++ is treated like an array of characters, so you can write

const char* rawString = "I'm a regular old string!";

Because char and wchar_t aren't necessarily the same type, you can't write

const wchar_t* rawString = "I'm a regular old string!"; // Error!

because there's a type mismatch: you've got an array of chars on the right-hand side and a pointer of type const wchar_t* on the left. As a result, C++ lets you define wide string literals by prefixing a string literal with an L. the resulting string is then an array of elements of type wchar_t, so this will compile:

const wchar_t* rawString = L"I'm a wide string!"; // Totally fine!

Microsoft's alias LPCWSTR is essentially a const wchar_t*, which is why you need the L prefix.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    *C++ has two character types* No love for `char16_t` and `char32_t`? – DeiDei Mar 15 '17 at 17:52
  • @DeiDei I didn't know those existed, actually. When did those get introduced? – templatetypedef Mar 15 '17 at 17:52
  • That would be with the C++11 revision. – DeiDei Mar 15 '17 at 17:53
  • 1
    @DeiDei Huh, I thought I knew all the new features that added. Guess I have some reading to do! Thanks for letting me know! – templatetypedef Mar 15 '17 at 17:53
  • Just to be clear, it's perfectly normal for professional codes and stuff to have L infront of strings now and then? I haven't seen it too often so it has gotten me curious as to if I have done something wrong. – JohnSilver Mar 15 '17 at 17:56
  • @JohnSilver It's part of the standard, so it's perfectly legal. I'm not sure how widely-used this prefix is, though, since there's a bit of a sense that `wchar_t` wasn't thought through very well (it doesn't play well with Unicode, for example), though I'm ready to be corrected. – templatetypedef Mar 15 '17 at 17:57
  • Sorry if I sound very confused, because I might be at times when we talk about this. But, "so it's perfectly legal", the code errors unless I have an L infront of there, so apparently I am forced to. I read somewhere that unicode should be on aswell. – JohnSilver Mar 15 '17 at 17:59
  • @JohnSilver @templatetypedef You see it all the time when interacting with the Win32 API. Basically everything takes `LPCWSTR` when you use the "Unicode" variant. – Miles Budnek Mar 15 '17 at 18:00
  • Another short question though, kinda related to this. Why do people use the string data type from the string library when there are stuff like char and wchar_t? Again, sorry if I sound very confused. – JohnSilver Mar 15 '17 at 18:02
  • @JohnSilver `std::string` and it's variants (`std::wstring`, `std::u16string`, and `std::u32string`) are contianers that make manipulating and managing the lifetime of strings much easier than using raw `char*`s (or `whcar_t*`, `char16_t*`, and `char32_t*`). – Miles Budnek Mar 15 '17 at 18:04
  • Just one last thing, back to the L-topic. Am I absolutely forced to do this? It just seems abit unusual instead of directly writing the string,. I haven't seen it in other codes that much either. – JohnSilver Mar 15 '17 at 18:10
  • You can define the string as `LPCSTR` instead of `LPCWSTR` and avoid the `L`, but you will need to be sure to call the ANSI version of any WIN32 functions you call. – lcs Mar 15 '17 at 18:13
  • @JohnSilver when you build a program for Windows only, use `L"string"` always, in general no one is using ANSI APIs anymore. If you want to be platform independent, then that's another topic though... – zett42 Mar 15 '17 at 18:37
1

There is a way to have Ansi versus Unicode via project setting using TCHAR types and related functions, and a macro, but Ansi was last used for Windows NT and older versions. The switch to Unicode was done for Windows 2000 and later, so the tchar stuff is legacy, but Visual Studio will still create a default app using tchar on certain types of projects.

http://msdn.microsoft.com/en-us/library/windows/desktop/ff381407(v=vs.85).aspx

There are also some TCHAR based string functions.

For character strings, instead of the L, you could use the TEXT() macro

http://msdn.microsoft.com/en-us/library/windows/desktop/dd374074(v=vs.85).aspx

such as TEXT("example string"). This will create either an ansi string or unicode string based on the project setting for character set. You'll need to include windows.h for the TEXT macro.

Again, this is legacy code, except that if Visual Studio creates a default source program for you, it may use the TCHAR related stuff.

rcgldr
  • 27,407
  • 3
  • 36
  • 61