C预处理器:如何创建字符文字?

时间:2016-02-20 15:59:56

标签: c macros c-preprocessor

出于好奇,我想知道是否可以定义一个可以将其参数转换为字符文字的宏:

 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;
 }

两个可能的解决方案:

枚举所有字符

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

它不适用于MYMACRO(!),因为!不是C标识符的有效组件。

将参数转换为字符串文字

#define MYMACRO(x) #x [0]

它涉及指针取消引用,在案例标签等地方无效。

我不是要求一种方法来“改进”上面的switch语句本身。这只是一个玩具的例子。重复。这只是一个玩具示例。

2 个答案:

答案 0 :(得分:2)

这是我可能的解决方案:

#define EVAL(...) __VA_ARGS__
#define Q() '
#define MYMACRO(...) Q()EVAL(__VA_ARGS__)Q()

(Variadic宏用于支持MYMACRO(,),因为它将被解析为两个空参数。)

由于'不匹配,我不确定此代码是否符合标准。 不过,我认为这段代码适用于大多数C99编译器。 但是,此代码不适用于以下字符:

  • (必须与)
  • 匹配
  • )用于标识参数列表的开头和结尾
  • '"用于字符串文字和字符常量
  • \,需要转义
  • 空格字符,因为它们不是标记

我很确定没有适用于()'"的解决方案,因为如果允许,编译器必须改变解析宏参数的方式。

答案 1 :(得分:2)

虽然我无法获得user4098326的编译答案,但我确实得到了下面的解决方案来编译并按预期工作(在Code Composer Studio中)。关键是使用符号连接运算符。但请注意,根据标准,这不应该起作用。单引号(')不是有效的标记,也不是单引号后跟单个字符(' a)。因此,那些不应该是串联运算符的输入和输出。因此,我不建议实际使用此解决方案。

#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

然后:

switch(getchar()) {
   DO_CASE(A);
   DO_CASE(a);
   DO_CASE(!);
   default: printf("Neither a nor A nor !\n"); break;
 }