What Exactly Is the L Prefix in C++

What exactly is the L prefix in C++?

The literal prefixes are a part of the core language, much like the suffixes:

'a'    // type: char
L'a' // type: wchar_t

"a" // type: char[2]
L"a" // type: wchar_t[2]
U"a" // type: char32_t[2]

1 // type: int
1U // type: unsigned int

0.5 // type: double
0.5f // type: float
0.5L // type: long double

Note that wchar_t has nothing to do with Unicode. Here is an extended rant of mine on the topic.

What does the 'L' in front a string mean in C++?

It's a wchar_t literal, for extended character set. Wikipedia has a little discussion on this topic, and c++ examples.

What does the prefix L ... stand for in GCC C without #including wchar?

L'ÿ' is of type wchar_t, which can be implicitly converted into an unsigned short. L"ÿ" is of type wchar_t[2], which cannot be implicitly converted into unsigned short[2].

L prefix for strings in C++

The L prefix makes the string a wchar_t string.
You can use the Windows API function MultiByteToWideChar to convert an ANSI string to a wchar_t string.

Meaning of L near text in define

It means the string literal has type const wchar_t*, which is a type different that const char*. It is usually used to store Unicode strings.

Some APIs (particularly the Windows API) use this type all over the place.

What does L do?

If in doubt, consult the standard (§6.4.5, String Literals):

A character string literal is a
sequence of zero or more multibyte
characters enclosed in double-quotes,
as in "xyz". A wide string literal is
the same, except prefixed by the
letter L.

Note that it does not indicate that each character is a long, despite being prefixed with the same letter as the long literal suffix.

When does the prefix L matters for char or wchar_t literal?

Both cases fall under the rules for implicit conversions. Specifically the rules for integral conversions. The implicit conversion of char to whar_t should be well defined for all cases, as wchar_t is at least as wide as a char. Your compiler might warn you of the risk of data loss in the conversion from wchar_t to char, if the value of the wchar_t is (or can be in case the value isn't known at compile time) outside the range representable by char.

From my understanding the integer conversion rules applies to prvalue expressions of an integer type, characters are of integer type, and literals (except string literals) are prvalues, so this is why you see the behavior you see with the character literals, while you don't see it with string literals.

I don't have a version of the standard that I can look things up in, but I understand that cppreference is found to be a reasonable source of information. Hopefully it is accurate and I interpreted the rules correctly.

As for your question regarding finding the next space, you should probably split that into a separate question. With that said you should probably use std::isspace/std::iswspace (Unless you specifically only want ' '), and then have the compiler select the appropriate function based on T:

#include <type_traits>
#include <cwctype>
#include <cctype>

template <class T>
T* findNextSpace(T* str) {
if constexpr(std::is_same_v<T, char>) {
//Use std::isspace
}
else if(std::is_same_v<T, wchar_t>) {
//Use std::iswspace
}
else {
static_assert("Not implemented");
}
}

In case your compiler doesn't support the features used here, you can implement a similar solution using template specialization:

#include <cwctype>
#include <cctype>

template <class T>
struct isspace_helper;

template <>
struct isspace_helper<char> {
bool operator()(char c) const {
return std::isspace(c);
}
};

template <>
struct isspace_helper<wchar_t> {
bool operator()(wchar_t c) const {
return std::iswspace(c);
}
};

Obviously you could also use this with std::string as well (Because most people would suggest you used std::string instead over char/wchar_t arrays unless you have a good reason not to):

#include <algorithm>
#include <string>

template <class CharT, class Traits, class Alloc>
auto findNextSpace(std::basic_string<CharT, Traits, Alloc>& str) {
return std::find(str.begin(), str.end(), isspace_helper<CharT>{});
}

If your compiler doesn't support auto you can write std::basic_string<CharT, Traits, Alloc>::iterator instead. Then maybe provide an overloading accepting the string by const-reference for good measure.

How is L macro(?) defined?

L is not a macro, it's just the standard prefix for wide (wchar_t, "Unicode") string literals; the concept is similar to the L suffix for long int literals, f suffix for float literals and so on1.

By the way, if you are using TCHARs you shouldn't be using L directly; instead, you should use the _T() or TEXT() macro, that adds L at the beginning of the literal if the application is compiled "for Unicode" (i.e. TCHAR is defined as WCHAR), or adds nothing if the compilation target is "ANSI" (TCHAR defined as CHAR).


  1. Although in my opinion this is confusing - why suffixes for arithmetic types and a prefix for wide string literals?


Related Topics



Leave a reply



Submit