Post by Philipp Klaus KrauseHow can I put an integer constant into a string literal as a character?
I'm looking for a somewhat elegant macro M such that
#define I 255
const char *test = "test" M(I) "test";
after preprocessing ends up as
const char *test = "test" "\xff" "test";
(or the same string literal represented differently).
There isn't any way to do decimal to hex conversion in
the preprocessor. Character constants may use only hex
or octal escapes.
All I can think of at the moment is that your best bet is
to use octal.
#define I 377 /* must be 1 to 3 digits wide
#define STR(S) #S
#define M(OCT) STR(\OCT)
"abc" M(I) "xyz" /* expands t "abc" "\377 "xyz" */
The following would be better, but there is a problem:
#define I FF
#define STR(S) #S
#define M(HEX) STR(\x ## HEX)
The \x ## HEX operation produces an invalid token, which is
undefined behavior. It might work in many compilers, but
due to no requirement coming from ISO C.
There isn't any way to take material from a macro argument
such as HEX, and glue it with some preceding material without
an intervening space, other than the token pasting operator ##
which must produce a valid token.
The option of producing "\x" "FF" also doesn't exist; a character escape
in a string literal cannot be split across multiple literals
in this manner. What we have here is a string literal with
a bad \x syntax, followed by the string literal "FF" giving two
F characters.
If I had to solve this problem, I would avoid it entirely.
#define I "\xFF"
Then just use "test" I "test".
If these #defines are a primary objects, then just bite the bullet
and duplicate material as necessary: make separate macros which
give 255 as a numeric or character constant, and as a string
literal.
If the #define I is generated, tweak the generator to output
the information in the right form, and any additional forms.
There are ways to structure such parallel information.
Below, we write a macro which takes a pseudo-parameter P,
from which it calculates three different constants.
The caller passes in the expression I, which is itself not
defined as a macro, but which is used as a partial key for
retrieving three different macros.
$ gcc -E -x c -
#define I_STR "\xFF"
#define I_CHR '\xFF'
#define I_DEC 255
#define MX(PARAM, TYPE) PARAM ## _ ## TYPE
#define M(PARAM, TYPE) MX(PARAM, TYPE)
#define FUNNY_MACRO(P) do { \
int x = M(P, DEC); \
char c = M(P, CHR); \
char *s = "test" M(P, STR) "test" \
} while (0);
FUNNY_MACRO(I)
[Ctrl-D][Enter]
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "<stdin>"
# 14 "<stdin>"
do { int x = 255; char c = '\xFF'; char *s = "test" "\xFF" "test" } while (0);