出于好奇,我想知道是否可以定义一个宏来将其参数转换为字符文字:
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]
它涉及指针取消引用,并且在 case 标签等地方无效。
我并不是在寻求一种“改进”上述 switch 语句本身的方法。 这只是一个玩具示例。 重复。 这只是一个玩具示例。
虽然我无法得到 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;
}
这是我可能的解决方案:
#define EVAL(...) __VA_ARGS__
#define Q() '
#define MYMACRO(...) Q()EVAL(__VA_ARGS__)Q()
(可变参数宏用于支持
MYMACRO(,)
,因为它会被解析为两个空参数。)
由于不匹配的
'
,我不确定此代码是否符合标准。
不过,我认为这段代码适用于大多数 C99 编译器。
但是,此代码不适用于以下字符:
(
必须与 )
)
用于标识参数列表的开始和结束'
和 "
用于字符串文字和字符常量\
,需要转义我相当确定没有适用于
(
、)
、'
或 "
的解决方案,因为如果允许这样做,编译器将不得不更改解析宏参数的方式。
Microsoft 有 charizing 运算符
#@
但这是特定于编译器的。我发现 *#
在 VS 和 gcc 中都有效(可能还有更多),但我一辈子都不记得我从哪里得到它了。
#define MAKECHAR(x) *#x
导致声明
a = MAKECHAR(b);
扩大为
a = 'b';