有没有办法在宏中用其他语句嵌入pragma语句?
我正在努力实现以下目标:
#define DEFINE_DELETE_OBJECT(type) \
void delete_ ## type_(int handle); \
void delete_ ## type(int handle); \
#pragma weak delete_ ## type_ = delete_ ## type
Run Code Online (Sandbox Code Playgroud)
如果有的话,我可以使用提升解决方案(除了wave).
正如我之前的许多问题所述,我正在通过K&R工作,目前正在进入预处理器.其中一个更有意思的事情 - 我之前从未尝试过的任何学习C的尝试 - 是##预处理器操作员.根据K&R的说法:
预处理器运算符
##提供了一种在宏扩展期间连接实际参数的方法.如果替换文本中##的参数与a相邻,则参数将替换为实际参数,##并删除周围的空白区域,并重新扫描结果.例如,宏paste连接其两个参数:
#define paste(front, back) front ## back所以
paste(name, 1)创建令牌name1.
如何以及为什么有人会在现实世界中使用它?它的使用的实际例子是什么,有什么需要考虑的?
至少有一些C预处理器允许你将宏的值(而不是它的名称)通过一个类似函数的宏传递给另一个将它串行化的宏来进行字符串化:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
Run Code Online (Sandbox Code Playgroud)
这里的用例示例.
这确实有效,至少在GCC和Clang(两者都有-std=c99),但我不确定它是如何工作的C标准术语.
这种行为是否由C99保证?
如果是这样,C99如何保证呢?
如果不是,那么从C定义到GCC定义的行为在什么时候?
我试图找出如何使用C预处理器将#define'd int 连接到#define'字符串.我的编译器是CentOS 5上的GCC 4.1.该解决方案也适用于MinGW.
我想在字符串上附加一个版本号,但我能让它工作的唯一方法是将版本号的副本定义为字符串.
我能找到的最接近的东西是引用宏参数的方法,但它不适用于#defines
这不起作用.
#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" #MAJOR_VER #MINOR_VER
Run Code Online (Sandbox Code Playgroud)
它不没有工作,#小号或者是因为值为数字,它会扩大到"/home/user/.myapp" 2 6,这是无效的Ç.
这确实有效,但我不喜欢有版本定义的副本,因为我确实需要它们作为数字.
#define MAJOR_VER 2
#define MINOR_VER 6
#define MAJOR_VER_STR "2"
#define MINOR_VER_STR "6"
#define MY_FILE "/home/user/.myapp" MAJOR_VER_STRING MINOR_VER_STRING
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法将预处理器令牌转换为字符串.
具体来说,我在某处得到了:
#define MAX_LEN 16
Run Code Online (Sandbox Code Playgroud)
我想用它来防止缓冲区溢出:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
Run Code Online (Sandbox Code Playgroud)
我愿意通过其他方式来完成同样的事情,但仅限标准库.
我知道:
#define foo 4
#define str(s) #s
Run Code Online (Sandbox Code Playgroud)
与str(foo)写出:"foo"因为字符串化的第一个文本扩展的执行,但这样的:
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
Run Code Online (Sandbox Code Playgroud)
与xstr(foo)写出:"4".
为什么?该过程涉及哪些步骤?
我想将宏扩展的结果字符串化.
我试过以下内容:
#define QUOTE(str) #str
#define TEST thisisatest
#define TESTE QUOTE(TEST)
Run Code Online (Sandbox Code Playgroud)
并且TESTE扩展到:"TEST",而我正试图获得"thisisatest".我知道这是预处理器的正确行为,但任何人都可以帮我找到另一种方法吗?
Using TESTE #TEST is not valid
Using TESTE QUOTE(thisisatest) is not what I'm trying to do
Run Code Online (Sandbox Code Playgroud) 使用C预处理器时,可以像这样将字符串化为字符串:
#define TO_STRING(x) "a string with " #x
Run Code Online (Sandbox Code Playgroud)
所以使用时,结果如下:
TO_STRING(test) 将扩展到: "a string with test"
有没有办法做相反的事情?获取字符串文字作为输入参数并生成C标识符?例如:
TO_IDENTIFIER("some_identifier") 会扩大到: some_identifier
谢谢您的回答.
编辑:对于那些想知道我需要它的人:
我想通过字符串标识符来引用我的3D引擎的场景图中的节点,但同时避免在紧密循环中比较字符串.所以我想我会写一个简单的工具,它将在编译的预构建步骤中运行并搜索预定义的字符串 - 例如ID("something").然后,对于每个这样的令牌,它将计算括号之间的字符串的CRC32,并生成包含这些数字标识符的#defines的头文件.例如,对于字符串"something",它将是:
#define __CRC32ID_something 0x09DA31FB
然后,每个cpp文件将使用ID(x)宏包含生成的头文件.本ID("something")当然会扩大到__CRC32ID_something,所以在效果是什么,编译器会看到的是简单的整数标识符,而不是对人友好的字符串.当然,现在我只是满足于此,ID(something)但我认为使用引号会更有意义 - 一个不知道ID宏如何工作的程序员可以认为something没有引号是C标识符,而实际上这样的标识符不存在于所有.
在C++中是否可以对模板参数进行字符串化?我试过这个:
#define STRINGIFY(x) #x
template <typename T>
struct Stringify
{
Stringify()
{
cout<<STRINGIFY(T)<<endl;
}
};
int main()
{
Stringify<int> s;
}
Run Code Online (Sandbox Code Playgroud)
但我得到的是'T',而不是'int'.似乎预处理器在模板解析之前启动.
有没有其他方法可以做到这一点?
有没有办法在模板解析后进行预处理?(编译器是VC++).