How to single-quote an argument in a macro?
Asked Answered
R

6

13

I would like to create a C pre-processor macro that will single-quote the argument. Just like the common used #X.

I want Q(A) to be expanded to 'A'.

I am using gcc on Linux.

Does any one have an idea?

I know # double-quotes. I am looking for a similar mechanism for single-quoting.

Rappel answered 15/1, 2010 at 15:9 Comment(0)
N
18

The best you can do is

#define Q(x) ((#x)[0])

or

#define SINGLEQUOTED_A 'A'
#define SINGLEQUOTED_B 'B'
...
#define SINGLEQUOTED_z 'z'

#define Q(x) SINGLEQUOTED_##x

This only works for a-z, A-Z, 0-9 and _ (and $ for some compilers).

Nide answered 15/1, 2010 at 15:16 Comment(4)
Oh, that second method is pure evil ;-)Henke
$ is not a valid character for an identifier, according to the C standard. It may be accepted by some specific compilers, I suppose.Apfel
@Dale: Yes, GCC supports $ as an identifier. gcc.gnu.org/onlinedocs/gcc/Dollar-Signs.html#Dollar-SignsNide
Dale: Well, the standard allows for implementation-defined characters beyond digits, ASCII letters and the underscore. But that's probably not very portable, then :)Henke
A
7

Actually, #X double quotes its argument, as you can see with the following code.

#define QQ(X) #X
char const * a = QQ(A);

Run this with gcc -E (to just see the preprocessor output) to see

# 1 "temp.c"
# 1 "<built-n>"
# 1 "<command line>"
# 1 "temp.c"

char * a = "A"

To single quote your argument (which in C means that it's a single character) use subscripting

#define Q(X) (QQ(X)[0])
char b = Q(B);

which will be transformed into

char b = ("B"[0]);
Ancestral answered 15/1, 2010 at 15:20 Comment(0)
H
4

The best I can think of would be

#define Q(A) (#A[0])

but this isn't very pretty, admittedly.

Henke answered 15/1, 2010 at 15:11 Comment(0)
Y
1

this generates conversions:

#python
for i in range(ord('a'), ord('n')):
    print "#define BOOST_PP_CHAR_%s '%s'" % (chr(i), chr(i))

and this is preprocessor part:

#ifndef BOOST_PP_CHAR_HPP
#define BOOST_PP_CHAR_HPP

#define BOOST_PP_CHAR(c) BOOST_PP_CHAR_ ## c
//  individual declarations    

#endif // BOOST_PP_CHAR_HPP
Yeta answered 1/12, 2010 at 3:15 Comment(0)
F
1

I've just tried concatenation:

#define APOS           '
#define CHAR2(a,b,c)   a##b##c
#define CHAR1(a,b,c)   CHAR2(a,b,c)
#define CHAR(x)        CHAR1(APOS,x,APOS)

Unfortunately though, the preprocessor complains about an unterminated character. (and multicharacter if you have more than one character) A way to just disable preprocessor errors: (there is no specific warning option for this)

-no-integrated-cpp -Xpreprocessor -w

Some compile-time optimization example with some other tricks:

#define id1_id       HELP
#define id2_id       OKAY

#define LIST(item,...) \
    item(id1, ##__VA_ARGS__)\
    item(id2, ##__VA_ARGS__)\
    item(id1, ##__VA_ARGS__)\

#define CODE(id,id2,...)    ((CHAR(id##_id) == CHAR(id2##_id)) ? 1 : 0) +
int main() { printf("%d\n", LIST(CODE,id1) 0); return 0; }

This returns "2", since there are two items that have id1.

Fleda answered 6/2, 2013 at 14:50 Comment(0)
S
0

After some fiddling with macros I found the solution.

#define QUOTE_LITERAL() '
#define IN_QUOTES(x) QUOTE_LITERAL()x'

You will get warnings (for unterminated quotes) but can get rid of them with -no-integrated-cpp -Xpreprocessor -w. As mentioned by @darkfader

Sigurd answered 10/1 at 22:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.