2016-11-09 92 views
4

我想将一个十六进制值作为无符号整数传递给使用动态链接的方法。我作为参数传递的值以某种方式被损坏。发生什么事?为什么将unsigned int传递给performSelector会丢失比特?

- (void)callPerformSelector 
{ 
    NSNumber *argument = [NSNumber numberWithUnsignedInt:(unsigned int)0xFFFFFFFF]; 
    SEL selector = NSSelectorFromString(@"testPerformSelector:"); 
    NSLog(@"testPerformSelector object %@", argument); 
    [self performSelector:selector withObject:argument]; 
} 

- (void)testPerformSelector:(unsigned int) arg1 
{ 
    NSLog(@"testPerformSelector unsigned int %u", arg1); 
    NSLog(@"testPerformSelector hex %X", arg1); 
} 

输出是:

testPerformSelector object 4294967295 
testPerformSelector unsigned int 4294967283 
testPerformSelector hex FFFFFFF3 

回答

1

只能通过物体来选择,而不是原始类型,因此选择应该是:

- (void)testPerformSelector:(NSNumber *) arg1 
{ 
    NSLog(@"testPerformSelector hex %x", [arg1 unsignedIntValue]); 
} 

更新:正如指出的出由@ gnasher729,数字通过的原因似乎是-13是因为它是tagged pointer

+0

这是一个标记的指针。你看到的是数字的低24位,后跟8位标签。 – gnasher729

+0

@ gnasher729谢谢。更新了答案。 – Droppy

4

因为它应该是:

- (void)callPerformSelector 
{ 
    NSNumber *argument = @0xFFFFFFFF; 
    SEL selector = @selector(testPerformSelector:); 
    NSLog(@"testPerformSelector object %@", argument); 
    [self performSelector:selector withObject:argument]; 
} 

- (void)testPerformSelector:(NSNumber *) arg1 
{ 
    NSLog(@"testPerformSelector unsigned int %u", arg1.unsignedIntValue); 
} 

unsigned intNSNumber *是两回事

2

有一个简单的原因和复杂的原因。

简单的原因:为什么这不起作用performSelectorWithObject的目标的第一个参数必须是一个对象。您在函数签名中指定一个指向无符号整数的指针,但在调用它时传递一个对象(NSNumber)。因此,而不是:

- (void)testPerformSelector:(unsigned int) arg1 

你应该有

- (void)testPerformSelector:(NSNumber *) arg1 

然后,您将需要使用NSNumberunsignedIntValue得到0xFFFFFFFF出来的对象。

复杂的原因更有趣:为什么这几乎工作,看起来像失去了一些位。 NSNumber是一个包装数值的对象,它与原始数值非常不同。然而,NSNumber被实现为带标签的指针,因此尽管objective-c知道它是一个对象并将其当作一个对象对待,但NSNumber值的一个子集被实现为标记指针,其中实值被编码到“指针”中,而事实不是正常的指针在指针see Friday Q&A的(后来总是为零)底部四位中指示。

相关问题