How to Convert Concatenated Strings to Wide-Char with the C Preprocessor

How to convert concatenated strings to wide-char with the C preprocessor?

According to the C standard (aka "ISO-9899:1999" aka "C99"), Visual C is wrong and gcc is correct. That standard states, section 6.4.5/4:

In translation phase 6, the multibyte character sequences specified by any sequence of adjacent character and wide string literal tokens are concatenated into a single multibyte character sequence. If any of the tokens are wide string literal tokens, the resulting multibyte character sequence is treated as a wide string literal; otherwise, it is treated as a character string literal.

So you could file a complaint. Arguably, the previous version of the C standard (aka "C89" aka "C90" aka "ANSI C") did not mandate merging of wide strings with non-wide strings. Although C99 is now more than ten years old, it seems that Microsoft has no interest in making its C compiler conforming. Some users have reported being able to access some "C99" features by compiling C code as if it was C++ code, because C++ includes these features -- and for C++, Microsoft made an effort. But this does not seem to extend to the preprocessor.

In the C89 dialect, I think that what you are looking for is not possible (actually I am pretty sure of it, and since I have written my own preprocessor I think I know what I am talking about). But you could add an extra parameter and propagate it:

#define W(x)          W_(x)
#define W_(x) L ## x
#define N(x) x
#define STR(x, t) STR_(x, t)
#define STR_(x, t) t(#x)

#define LOCATION_(t) t(__FILE__) t("(") STR(__LINE__, t) t(")")
#define LOCATION LOCATION_(N)
#define WLOCATION LOCATION_(W)

which should work on both gcc and Visual C (at least, it works for me, using Visual C 2005).

Side note: you should not define macros with a name beginning with an underscore. These names are reserved, so by using them you could clash with some names used in system headers or in future versions of the compiler. Instead of _WIDEN, use WIDEN_.

How to convert #defined string literal to a wide string literal?

Token pasting needs an additional level of indirection to deal properly with macros used as operands. Try something like:

#define PASTE(x, y) x##y
#define MAKEWIDE(x) PASTE(L,x)

C Preprocessor - Use definitions as integer and as wide strings

Here's the tested solution:

#define VER_X_  0
#define VER_H_ 2
#define VER_M_ 0
#define VER_L_ 3

#define VERSION_N (VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_)

// Device Strings
//
#define STRINGIFY_1(x) L#x
#define STRINGIFY(x) STRINGIFY_1(x)
#define PASTE(x, y) x##y
#define MAKEWIDE(x) PASTE(L,x)

#define SERIALNUMBER_STR MAKEWIDE(STRINGIFY(VER_H_)) L"." \
MAKEWIDE(STRINGIFY(VER_M_)) L"." \
MAKEWIDE(STRINGIFY(VER_L_))

Thanks to ouah

EDIT:

  1. Added parentheses according to pat.
  2. Ouah's remark was taken seriously. Solution adapted to suit MS: Added two PASTE & MAKEWIDE

Standard macro to promote string literal to wchar_t in VC++

No, there is no "standard" macro for this. The standard is to prefix wide strings with an L and omit the prefix from narrow strings.

The only reason why such a macro even needs to exist is when you're variously targeting platforms that don't support Unicode. In that case, everything needs to be a narrow string. If you're not dealing with platforms that lack Unicode support, then everything should probably be a wide string all the time.

The _T and TEXT macros are provided in the Windows headers for precisely this purpose: maintaining a single code base that can be compiled both for Windows NT, which supports Unicode, and Windows 9x, which lacks Unicode support.

I can't imagine why you would need such a macro if you aren't already including the Windows headers, but if you do, it's pretty simple to write one yourself. Except than you're going to need to know when string literals should be wide strings and when they should be narrow strings. There's no "standard" #define for this, either. The Windows headers use the UNICODE pre-processor symbol, but you can't rely on this being defined on other platforms. So now you're back to where you started from.

Why do you think you need a macro for this, again? If you're hardcoding the type of the string as wchar_t*, then you're always going to want to use a wide character literal, so you always want to use the L prefix.

When you're using the _T and/or TEXT macros from the Windows headers, you're also not hard-coding the type of the string as wchar_t*. Instead, you're using the TCHAR macro, which automatically resolves to the appropriate character type depending on the definition of the UNICODE symbol.

Combining wide string literal with string macro

Did you try

#define APPNAME "MyApp"

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)

const wchar_t *AppProgID = WIDEN(APPNAME) L".Document";

C Macro should expand as char* in one place and wchar* in another place with L character

A quick and easy solution, with no extra macros:

  • Use MACRO_STRING directly when you need char *.
  • Use L"" MACRO_STRING when you need wchar_t *.

Concatenate int to string using C Preprocessor

Classical C preprocessor question....

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)

The extra level of indirection will allow the preprocessor to expand the macros before they are converted to strings.

String concatenation using preprocessor

Concatenation of adjacent string litterals isn't a feature of the preprocessor, it is a feature of the core languages (both C and C++). You could write:

printf("Hello "
" world\n");


Related Topics



Leave a reply



Submit