带有布尔参数的 Objective-C 方法中奇怪的“选择器修饰”

Posted

技术标签:

【中文标题】带有布尔参数的 Objective-C 方法中奇怪的“选择器修饰”【英文标题】:Strange "selector mangling" in Objective-C method with Boolean arguments 【发布时间】:2013-02-03 15:40:08 【问题描述】:

我需要在运行时通过反射调用动态恢复方法名称。但有些人会得到奇怪的结果。

我的 TestClass 包含如下方法:

- (void)testMethod6_NSRect:(NSRect)a1 int:(int)a2 int:(int)a3 bool:(Boolean)a4 
    ...

当使用 class_copyMethodList() 枚举上述类方法并通过 method_getName() 获取方法选择器时,我得到:

"testMethod6_NSRect:int:int:_Bool:" 

因此,选择器以某种方式被重写(通过 gcc?)以从“bool”生成“_Bool”。据我测试,这似乎只适用于“布尔”选择器部分 - 如果我将其更改为 int:(int),如下所示:

- (void)testMethod1_int:(int)a1 int:(int)a2 int:(int)a3 int:(int)a4 
    ...

我得到了预期:

"testMethod1_int:int:int:int:"

问: 有谁知道规则或指向我可以在哪里找到它们以进行“选择器重写”的指针,还是我遗漏了什么?这仅适用于“布尔”吗? 我还需要知道这种行为是否取决于 gcc-version、osx-version 或运行时库版本。

我正在使用(gcc --version): i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3) 在 (uname -a) 10.8.0 达尔文内核版本 10.8.0:

【问题讨论】:

这很吸引人;我猜 GCC 看到 bool 并将其转换为它的底层类型名称,但没有意识到它是选择器的一部分。您是否尝试过切换到 Clang 编译器? 尝试在方法中打印_cmd。此外,如果可能,您应该使用 llvm。 【参考方案1】:

问题在于 C99 标准头文件 <stdbool.h> 中的一个丑陋的预处理器魔法:

#define bool _Bool

C99 定义了一个名为 _Bool 的类型,其行为类似于 C++ 的 bool 类型。定义是为了能够在 C 中使用它,但需要使用 C++ 标识符。

解决方案:

#undef bool

【讨论】:

谢谢——这就是问题所在;虽然我认为让选择器部分通过预处理器翻译是一个 gcc 错误 - 而不是整个选择器......但由于我无法控制我加载的类(二进制),我可能不得不假设,这已经发生在任何已编译的类中......(我想知道有多少其他这样的错误翻译已经找到了进入二进制文件的方式......) 这是 cpp(C 预处理器)的所有(一致)实现的问题:预处理器根本不理解该语言。您可以很容易地找到其他示例,其中它不符合您的预期。所以,不,这不是一个错误,而是预期和依赖的行为。尽管如此,还是很烦人。 如果您打算通过预处理器指令翻译选择器怎么办?预处理器就是它的本质 - 一种语言无意识的文本处理器。这不是错误,它的行为符合指定。【参考方案2】:

尝试使用 BOOL 而不是 Boolean

【讨论】:

相同的行为。它似乎是选择器的功能,而不是参数类型。此外,由于我无法控制需要反映的代码,因此我无法阻止遇到具有这样名称的方法(即,即使它确实有所作为,它看起来也不是一个通用的解决方案我的问题)...

以上是关于带有布尔参数的 Objective-C 方法中奇怪的“选择器修饰”的主要内容,如果未能解决你的问题,请参考以下文章

iPhone应用程序中奇怪的状态栏偏移

R(e1071)中奇怪的 svm 行为

xcode中奇怪的segue动画

CodeIgniter 2.0.3 中 Active Record 中奇怪的反引号行为

你能给我一些 C++ 中奇怪的单行注释的例子吗?

javascript中奇怪事件