预处理宏值转换为Objective-C字符串字面量

28

我在构建设置中定义了一个预处理器宏

FOO=BAR

我想把那个值转换为一个Objective-C字符串字面量,以便可以将其传递给一个方法。以下的#define语句不能正常工作,但它应该说明我试图实现的目标:

 #define FOOLITERAL @"FOO" //want FOOLITERAL to have the value of @"BAR"

 myMethodThatTakesAnNSString(FOOLITERAL);

我希望我只是错过了什么显而易见的东西,但我似乎找不到正确的预处理器魔法以获得我所需的内容。

5个回答

36

使用字符串转换操作符#将符号转换为C字符串。然而,由于预处理器的一个怪异问题,您需要使用两个额外的宏层级:

#define FOO BAR
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define FOOLITERAL @ STRINGIZE2(FOO)
// FOOLITERAL now expands to @"BAR" 
额外添加这些层次结构的原因是,字符串化操作符只能用于宏的参数,而不能用于其他记号。其次,如果宏的某个参数在宏体中使用字符串化运算符,则该参数不会被扩展为另一个宏。因此,我们需要将其包装在另一个宏中,以确保FOO得到扩展。这样,当STRINGIZE2被扩展时,它也会扩展FOO,因为字符串化操作符不出现在该宏的主体中。

搞定了。我尝试过双重间接引用,但是“@”作为宏值似乎让它混淆了。一个小区别是第一行不代表我的情况,因为它没有检索构建设置#define FOOVAL FOO #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define FOOLITERAL @ STRINGIZE2(FOOVAL)这就是实际上对我有用的。但是你的答案帮助了我。 - vagrant
嗨@vagrant。这个解决方案在LLVM上仍然适用吗?我正在尝试让它工作,但是在我的构建设置预处理器宏中定义的FOO的实际值从未显示出来。您可以更新您的问题并提供对您有效的解决方案吗?干杯。 - epologee
1
为什么不直接使用 #define Helper(STR) @ #STR - tadeuzagallo
1
这是正确的,但在我看来,下面@Noa的答案更容易使用。 - Adam
如果FOO的值中有逗号,似乎无法正常工作。 - Albert Renshaw

29

这是Adam Rosenfield回答的修改版,语义更清晰:

#define NSStringize_helper(x) #x
#define NSStringize(x) @NSStringize_helper(x)

我用它来替换像这样的代码:

case OneEnumValue: name = @"OneEnumValue"; break;
case AnotherEnumValue: name = @"AnotherEnumValue"; break;

使用这个:

#define case_for_type(type) case type: name = NSStringize(type); break

case_for_type(OneEnumValue);
case_for_type(AnotherEnumValue);

3

在Foundation.framework中包含了SDK的/usr/include/os/base.h,预定义了一个便捷的宏OS_STRINGIFY(s),与此同时保留了HTML标签,因此您可以直接使用下面的代码而无需进行其他定义。

myMethodThatTakesAnNSString(@OS_STRINGIFY(FOO));

很好的发现。本质上是被接受答案的解决方案,但可以一致地使用,而不会在应用程序代码中混杂着已经存在于苹果框架中的东西:https://opensource.apple.com/source/xnu/xnu-4903.241.1/libkern/os/base.h.auto.html - Nate

0
你需要定义预处理器宏,例如:
FOO=\@\"BAR\"

并在代码侧使用,

[NSString stringWithFormat:@"macro: %@", FOO];

-2
你具体看到了什么错误?这种类型的事情确实可以按照你的期望工作:
#define kMyString @"MyString"

[NSString stringWithFormat:@"macro: %@", kMyString];

3
所需字符串的实际值是预处理器宏的值。因此,我不能像您的示例中那样将值直接放入代码中,它必须来自FOO变量。 - vagrant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接