我在我的应用程序中比较两个 NSNumbers,但我做错了:
if(max < selected)
它应该是:
if([max longValue] < [selected longValue])
所以第一个比较实际上是比较两个对象的内存地址,有趣的是(至少对我而言)是值似乎与地址有关。例如,如果我得到第一个值为 5
的数字,它的内存地址是 0xb000000000000053
如果我得到第二个值为 10
的是 0xb0000000000000a3
(“a”相当于十六进制的 10)。
因此,第一个比较(错误)实际上是有效的。现在一个用户提示这里有一个错误,显然是因为这个,但它让我想到了下一个问题:
这是否只发生在模拟器中?因为它是我正在测试的地方,用户将拥有一个真实的设备。或者也许这通常会发生,但它不是一个总是满足的规则?
最佳答案
这是一个“标记指针”,而不是地址。如您所见,值 5 包含在指针内。您可以识别标记指针,因为它们是奇数(最后一位是 1)。不可能在任何 Apple 硬件上获取奇数地址(字大小为 4 或 8 字节),因此该位永远不会设置为真实地址。
标记指针仅在 64 位平台上可用。如果您在 32 位平台上运行,那么这些值将是真正的指针,并且它们可能没有任何特定的顺序,这将导致您遇到的各种错误。不幸的是,我不认为有任何方法可以获得编译器警告,甚至是针对 NSNumber 上的这种滥用的静态分析警告。
Mike Ash provides an in-depth discussion of the subject.
稍微相关一点,在 32 位平台上,某些 NSNumber 是单例,特别是小值,因为它们被大量使用(我记得是 -1 到 12,但我相信它在不同的平台上是不同的)。这意味着 ==
可能碰巧适用于某些数字,但不适用于其他数字。这也意味着在没有 ARC 的情况下,可能会过度释放特定值(例如 4),这样您的程序在下次碰巧使用该值时就会崩溃。真实的故事....很难调试。
关于ios - 内存地址是否遵循 iOS 中的模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58557989/