我的猜测是这个问题的答案是否定的,但如果有办法的话会很棒.为了澄清,假设我有以下宏:
#define MY_VARIADIC_MACRO(X...) // Does some stuff here in the macro definition
Run Code Online (Sandbox Code Playgroud)
我想要做的是以某种方式对X的所有变量执行字符串化,然后将其传递给可变参数函数; 这里的关键字是之前的.我知道有没有办法真正从接入宏定义中的各个参数,但有没有办法字符串化所有参数,与可能类似于下面的东西?
#define MY_VARIADIC_MACRO(X...) some_variadic_function("some string", #X)
Run Code Online (Sandbox Code Playgroud) #define JNI_DECLARE( classname, methodname ) \
classname ## methodname( JNI* env )
#define JAVA_CLASS Java_com_example
void JNI_DECLARE( JAVA_CLASS, open ) {}
Run Code Online (Sandbox Code Playgroud)
这扩展到:
void JAVA_CLASS_open( JNI* env ) {}
Run Code Online (Sandbox Code Playgroud)
如何得到:
void Java_com_example_open( JNI* env ) {}
Run Code Online (Sandbox Code Playgroud)
?
我想在它与其他东西连接之前评估一个令牌."问题"是标准将行为指定为
在重新检查替换列表以更换更多宏名称之前,删除替换列表中的##预处理标记的每个实例(不是来自参数),并将前面的预处理标记与以下预处理标记连接起来.
因此在下面的例子中,
#include <stdlib.h>
struct xy {
int x;
int y;
};
struct something {
char * s;
void *ptr;
int size;
struct xy *xys;
};
#define ARRAY_SIZE(a) ( sizeof(a) / sizeof((a)[0]) )
#define DECLARE_XY_BEGIN(prefix) \
struct xy prefix ## _xy_table[] = {
#define XY(x, y) {x, y},
#define DECLARE_XY_END(prefix) \
{0, 0} \
}; \
struct something prefix ## _something = { \
"", NULL, \
ARRAY_SIZE(prefix ## _xy_table), \
&(prefix ## _xy_table)[0], \
};
DECLARE_XY_BEGIN(linear1)
XY(0, 0) …Run Code Online (Sandbox Code Playgroud) 我想创建一个C预处理器宏,它将引用该参数.就像常用的一样#X.
我想Q(A)扩大到'A'.
我在Linux上使用gcc.
有人有想法吗?
我知道#双引号.我正在寻找一种类似的单引号机制.
我一直在尝试在C中实现一个函数宏,它将"DEBUG:"添加到参数中,并将其参数传递给printf:
#define DBG(format, ...) printf("DEBUG: " #format "\n", __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
这给了我gcc中的这个错误:
src/include/debug.h:4:70: error: expected expression before ‘)’ token
#define DBG(format, ...) printf("DEBUG: " #format "\n", __VA_ARGS__)
^
Run Code Online (Sandbox Code Playgroud)
据说,它应该串行化格式,并将其变量参数传递给printf,但到目前为止,我无法通过此错误.
编辑
在放弃了字符串化参数和double-hashing(##)后,__VA_ARGS__我现在有了这个错误:
src/lib/cmdlineutils.c: In function ‘version’:
src/lib/cmdlineutils.c:56:17: warning: ISO C99 requires rest arguments to be used [enabled by default]
DBG("version()");
Run Code Online (Sandbox Code Playgroud)
我应该在争论后放置逗号吗?
DBG("version()",); // ?
Run Code Online (Sandbox Code Playgroud)
作为参考,DBG()现在看起来像这样:
#define DBG(format, ...) printf("DEBUG: " format "\n", ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud) 我想使用一个#include带有文件名的指令,该指令作为外部定义的宏传递.
例如
#include #FILE".h"
Run Code Online (Sandbox Code Playgroud)
where FILE将被定义为字符串MyFile(不带引号),从而导致
#include "MyFile.h"
Run Code Online (Sandbox Code Playgroud)
此处不能使用字符串化运算符#,因为符号FILE不是宏参数.我尝试过其他方法,但无济于事.
你看到了解决方案吗?
我想做的(用于记录目的)是这样的:
编写此代码是为了显示我的问题,实际代码很复杂,是的,我有充分的理由在C++上使用宏=)
# define LIB_SOME 1
# define LIB_OTHER 2
# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
" at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)
LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")
Run Code Online (Sandbox Code Playgroud)
LOG_ERROR_SIMPLE() 写入lib参数的字符串化(由""包围的宏名称)
但随后LOG_ERROR写入已扩展的宏的字符串化("2").这是预期的,因为lib在扩展和调用之前得到了扩展LOG_ERROR_SIMPLE.但这不是我需要的.
基本上我的问题是:如何在调用另一个宏函数时避免宏函数参数的宏扩展?
我使用了一个避免宏扩展的技巧:
LOG_ERROR(ptr, lib, str, x) LOG_ERROR_SIMPLE(ptr, …Run Code Online (Sandbox Code Playgroud) 考虑一下:
#define STRINGIFY(A) #A
Run Code Online (Sandbox Code Playgroud)
如果我后来写道:
STRINGIFY(hello)
Run Code Online (Sandbox Code Playgroud)
编译器实际上看到了这个:
#hello
Run Code Online (Sandbox Code Playgroud)
我认为前面的额外哈希#A让我感到困惑.
我正在使用这个预处理器宏来"字符串化"并从定义解析函数中轻松返回:
#define STRINGIFY_RETURN(x) case x: return #x ""
Run Code Online (Sandbox Code Playgroud)
它就像MBSC环境中的魅力一样,具有正常的字符串文字.例:
#define MY_DEFINE_1 1
#define MY_DEFINE_2 2
#define MY_DEFINE_3 3
const char* GetMyDefineNameA(unsigned int value)
{
switch(value)
{
STRINGIFY_RETURN(MY_DEFINE_1);
STRINGIFY_RETURN(MY_DEFINE_2);
STRINGIFY_RETURN(MY_DEFINE_3);
default: return "Unknown";
}
}
Run Code Online (Sandbox Code Playgroud)
但是我不得不越来越多地切换到Unicode兼容性,所以我不得不重写这个函数来返回Unicode字符串,这需要L在字符串文字前加前缀.所以我尝试过:
#define STRINGIFY_RETURN_WIDE(x) case x: return #x L""
const wchar_t* GetMyDefineNameW(unsigned int value)
{
switch(value)
{
STRINGIFY_RETURN_WIDE(MY_DEFINE_1);
STRINGIFY_RETURN_WIDE(MY_DEFINE_2);
STRINGIFY_RETURN_WIDE(MY_DEFINE_3);
default: return L"Unknown";
}
}
Run Code Online (Sandbox Code Playgroud)
但这给了我错误:
错误C2308:连接不匹配的字符串
错误C2440:'return':无法从'const char [12]'转换为'const wchar_t*
我也尝试过:
#define STRINGIFY_RETURN_WIDE(x) case x: return L #x ""
#define STRINGIFY_RETURN_WIDE(x) case x: return …Run Code Online (Sandbox Code Playgroud) 是否可以对此C宏进行字符串化:
#define GPIO_INT_PIN (GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)
Run Code Online (Sandbox Code Playgroud)
使用类似的东西
MY_STRINGFY(GPIO_INT_PIN)
Run Code Online (Sandbox Code Playgroud)
要得到
"(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)" ?