2

I was reading through the source code of glibc and I found that it has two macros which have the same name
This one is on the line 105
#define L_(Str) L##Str
and this on the line 130
#define L_(Str) Str

What do these macros really mean ? The usage is only for comparing two characters
For example on line 494, you could see it is used for comparing character values between *f and '$'
if(*f == L_('$')). If we wanted to compare the two characters, we could have compared them directly, instead of directing them through a macro ? Also, what is the use case for the macro on line 105 ?

Palash Ahuja
  • 522
  • 1
  • 5
  • 15
  • 1
    If you take a closer look you will see that the two macro definitions are mutually exclusive, using *conditional compilation*. You should also take some time to read about *wide characters* and *wide character strings*. – Some programmer dude Jul 12 '17 at 06:20
  • 1
    And what does the comparison have to do with the macros? Please show the *complete* lines you reference. – Some programmer dude Jul 12 '17 at 06:21

2 Answers2

8

It prepends macro argument with L prefix (wchar_t literal - it uses as large datatype as is needed to represent every possible character code point instead of normal 8 bit in char type) if you're compiling wscanf version of function (line 105). Otherwise it just passes argument as it is (line 130).

## is string concatenation operator in c preprocessor, L##'$' will expand to L'$' eventually.

To sum up: it is used to compile two, mutually exclusive versions of vscanf function - one operating on wchar_t, one on char.

Check out this answer: What exactly is the L prefix in C++?

rkrahl
  • 1,159
  • 12
  • 18
  • 1
    On 32-bit (or larger) systems supporting Unicode, then `wchar_t` is *usually* 32 bits representing a Unicode code-point. The notable exception is Windows where `wchar_t` is a 16-bit type representing a UTF-16 encoded character. Otherwise `wchar_t` just has "to be large enough to represent any supported character code point" (quoted from [this fundamental type reference](http://en.cppreference.com/w/cpp/language/types)). – Some programmer dude Jul 12 '17 at 06:28
  • Thanks for the help !! – Palash Ahuja Jul 12 '17 at 06:31
  • @Someprogrammerdude thanks, didn't know that. I've changed my answer. – rkrahl Jul 12 '17 at 06:34
2

Let's read the code. (I have no idea what it does, but I can read code)

First, why are there two defines as you point out? One of them is used when COMPILE_WSCANF is defined, the other is used otherwise. What is COMPILE_WSCANF? If we look further down the file, we can see that different functions are defined. When COMPILE_WSCANF is defined, the function we end up with (through various macros) is vfwscanf otherwise we get vfscanf. This is a pretty good indication that this file might be used to compile two different functions one for normal characters, one for wide characters. Most likely, the build system compiles the file twice with different defines. This is done so that we don't have to write the same file twice since both the normal and wide character functions will be pretty similar.

I'm pretty sure that means that this macro has something to do with wide characters. If we look at how it's used, it is used to wrap character constants in comparisons and such. When 'x' is a normal character constant, L'x' is a wide character constant (wchar_t type) representing the same character.

So the macro is used to wrap character constants inside the code so that we don't have to have #ifdef COMPILE_WSCANF.

Art
  • 19,807
  • 1
  • 34
  • 60