如果我在C中定义了一个常量字符,我可以将它合并为一个字符串文字吗?
#ifdef WIN32
# define SEP '\\'
# define ALTSEP '/'
#else
# define SEP '/'
# define ALTSEP '\\'
#endif
#define SOME_STRING_LITERAL "foo"
/* code snippet */
/* Desired string: "prefix_foo/bar" */
const char *path = "prefix_" SOME_STRING_LITERAL SEP "bar";
当然这会失败,因为SEP
没有被定义为字符串文字,但有没有办法使SEP
正确连接?或者我需要另一个定义,例如#define SEP_STR "/"
。
答案 0 :(得分:2)
我认为你不能用C做到这一点。
核心问题是"
符号非常重要,即使在预处理器知道应该将其视为预处理令牌之前,它也会得到解释。
使用#运算符进行字符串化不会有帮助。即使你写了像
这样的宏#define STRINGINIZE(x) #x
#define CHAR_TO_STR(ch) STRINGINIZE(ch)
然后将其作为
调用const char *path = "prefix_" SOME_STRING_LITERAL CHAR_TO_STR(SEP) "bar";
它对你没有好处,因为你最终会得到像
这样的字符串prefix_foo`\`bar
你也做不到这个:
const char *path = "prefix_" SOME_STRING_LITERAL CHAR_TO_STR(SEP)[1] "bar";
因为它与我们在第一时间所拥有的相同,所以它不会被编译。
此外,您无法基于串联预处理器令牌来制定解决方案,因为"
是比##
更基本的符号。
所以唯一的解决方案似乎是将字符声明为字符串文字。
答案 1 :(得分:0)
您可以使用编译时字符串化运算符#
#define SEP_STR(x) #x
#define SEP_STR_2(x) SEP_STR(x)
const char *path = "prefix_" SOME_STRING_LITERAL SEP_STR_2(SEP) "bar";
或者您可以将SEP
定义为"\\"
。
简而言之:
如果要对宏参数的扩展结果进行字符串化,则必须使用两级宏。
答案 2 :(得分:0)
不要将SEP定义为字符,而是将其定义为字符串。
#include <stdio.h>
#define SEP "\\"
#define SOME_STRING_LITERAL "foo"
int main() {
const char * path = "prefix_" SOME_STRING_LITERAL SEP "bar";
puts(path);
return 0;
}
输出:prefix_foo\bar