【问题标题】:Bug in Clang function-like macro parsing with Objective C variadic method call?使用 Objective C 可变参数方法调用的 Clang 类函数宏解析中的错误?
【发布时间】:2015-08-25 14:23:26
【问题描述】:

考虑以下调用:

NSString* localized = NSLocalizedString([NSString stringWithFormat:@"Hello %@", @"World"], @"");

它有什么问题?我看不出任何本质上的错误,但是编译器/预处理器抱怨传递给它的参数太多。 另一方面,以下两个编译:

显式变量:

NSString* string = [NSString stringWithFormat:@"Hello %@", @"World"];
NSString* localized = NSLocalizedString(string, @"");

用括号括起来:

NSString* localized = NSLocalizedString(([NSString stringWithFormat:@"Hello %@", @"World"]), @"");

看起来预处理器/编译器错误地解析了, 字符。

我在 Xcode 7 beta 6 中得到了这个,所以它可能是 Clang 工具链中的一个新错误。

【问题讨论】:

  • 向 Apple 提交错误报告。
  • @rmaddy 我做了,#22418824
  • BTW - NSLocalizedString 的第一个参数不应该是字符串文字吗?请记住,您使用命令行工具gestrings 来生成本地化字符串文件。这意味着它只是解析您的源代码文件。根据运行时值定义键是没有意义的。
  • 是的,上面的例子感觉不强。我的意思是让格式本身本地化,但这样做是错误的。不过,很酷的错误。 :-)
  • @rmaddy 严格来说,你所说的不是真的。我可以自己生成字符串文件,并将我想要的所有可能的动态值作为字符串。这可能的。

标签: objective-c macros clang xcode7 xcode7-beta6


【解决方案1】:

这不是错误,它是 C 预处理器的工作方式。来自 C 标准:

由最外面的匹配括号界定的预处理标记序列形成了类函数宏的参数列表。列表中的各个参数由逗号预处理标记分​​隔,但匹配内括号之间的逗号预处理标记不分隔参数。

所以逗号分隔宏参数除非它们在匹配的内括号内 - 这是你的“用括号括起来”变体作品。 C不讨论匹配括号[],只有括号(),所以你的第一个例子有三个宏参数:[NSString stringWithFormat:@"Hello %@"@"World"]@""。预处理发生在语法分析之前,因此前两个参数在 (Objective-)C 中没有语法意义的脂肪并不重要。

HTH

【讨论】:

  • 但这是一个正在预处理的.m 文件。这个预处理器不应该像熟悉 C 语法括号一样扩展为熟悉 Objective C 语法括号吗?
  • @LeoNatan - 这是一个不同的问题! ;-) 应该是?可以吗?请记住,宏扩展被定义为发生在 语法分析之前,因此虽然它可以完成,但它并不像听起来那么简单。您还需要确保这样的更改不会破坏任何 C 宏的用法,请记住 Objective-C 是 C 的超集,所有标准 C 都应该无错误地编译。
  • 顺便说一句,Apple 的更好解决方法是将 NSLocalizedString 定义为内联函数,这既可以避免您遇到的问题,又可以提供更多“正常”行为(每个参数只评估一次,等等) .
  • 同意,最佳解决方案。
  • @LeoNatan Objective-C 完全符合 C 标准(接受额外的关键字),因此来自 C 的预处理器应该与在 C 中的工作方式完全相同。人们可以依赖于定义的行为在 C 中,在编写 Objective-C 代码时。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
相关资源
最近更新 更多