Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C preprocessor: How to create a character literal?

Just out of curiosity, I'd like to know if it is possible to define a macro which can turn its argument into a character literal:

 switch(getchar()) {
   case MYMACRO(A): printf("Received A\n"); break;
   case MYMACRO(a): printf("Received a\n"); break;
   case MYMACRO(!): printf("Received an exclamation mark\n"); break;
   default: printf("Neither a nor A nor !\n"); break;
 }

Two possible solutions off the top of my head:

Enumerating all characters

#define LITERAL_a 'a'
#define LITERAL_b 'b'
...
#define MYMACRO(x) LITERAL_ ## x

It doesn't work with MYMACRO(!) because ! is not a valid component of a C identifier.

Convert the parameter into a string literal

#define MYMACRO(x) #x [0]

It involves a pointer dereference and is invalid in places like a case label.

I'm not asking for a way to "improve" the above switch statement itself. It's just a toy example. Repeat. It's just a toy example.

like image 928
nodakai Avatar asked Feb 20 '16 15:02

nodakai


People also ask

What is character literal in C?

A character literal contains a sequence of characters or escape sequences enclosed in single quotation mark symbols, for example 'c' . A character literal may be prefixed with the letter L, for example L'c' .

What does ## mean in C preprocessor?

The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.

What is Stringizing operator in C?

The number-sign or "stringizing" operator (#) converts macro parameters to string literals without expanding the parameter definition. It's used only with macros that take arguments.

How do you define a string macro?

We can create two or more than two strings in macro, then simply write them one after another to convert them into a concatenated string. The syntax is like below: #define STR1 "str1" #define STR2 " str2" #define STR3 STR1 STR2 //it will concatenate str1 and str2.


1 Answers

While I couldn't get user4098326's answer to compile, I did get the solution below to compile and work as expected (in Code Composer Studio). The key was to use the symbol concatenation operator. Note however, that according to the standard, this should not work. A single quote (') is not a valid token nor is a single quote followed by a single character ('a). Thus those should not be able to be the input nor output of the concatenation operator. Thus, I would not recommend actually using this solution.

#define CONCAT_H(x,y,z) x##y##z
#define SINGLEQUOTE '
#define CONCAT(x,y,z) CONCAT_H(x,y,z)
#define CHARIFY(x) CONCAT(SINGLEQUOTE , x , SINGLEQUOTE )

#define DO_CASE(...) case CHARIFY(__VA_ARGS__): printf("Got a " #__VA_ARGS__ "\n"); break

Then:

switch(getchar()) {
   DO_CASE(A);
   DO_CASE(a);
   DO_CASE(!);
   default: printf("Neither a nor A nor !\n"); break;
 }
like image 159
Rick Avatar answered Sep 19 '22 08:09

Rick