我最近浪费约半小时跟踪在此的NSLog古怪的行为(...):

NSString *text = @"abc";
long long num = 123;
NSLog(@"num=%lld, text=%@",num,text); //(A)
NSLog(@"num=%d, text=%@",num,text); //(B)

线(A)打印预期 “NUM = 123,文本= ABC”,但线(B)打印 “NUM = 123,文本= <强>(空)”。

显然,打印具有long long一个%d是一个错误,但有人可以解释为什么它会导致text要被打印为空?

有帮助吗?

解决方案

您刚刚搞砸内存对齐在栈上。我想比你使用最新的苹果产品与x86处理器。考虑到这些假设,考虑你的筹码看起来,在这两种情况下:

   |      stack          | first | second |
   +---------------------+-------+--------+
   |        123          |       |  %d    |
   +---------------------+ %lld  +--------+
   |         0           |       |  %@    |
   +---------------------+-------+--------+
   |   pointer to text   | %@    |ignored |
   +---------------------+-------+--------+  

在第一种情况下,你把堆8个字节,然后4字节。比的NSLog被指示采取从堆靠背12个字节(%lld 8个字节和4个字节为%@)。

在第二情况下,你指示的NSLog先进行4个字节(%d)。由于您的变量是8个字节长,并保持非常小的数目的上部4个字节将为0。然后,当将NSLog的尝试打印文本将采取nil从栈。

由于发送消息nil是的OBJ-C的NSLog有效将只发送给description:得到nil没有可能,然后打印(空)。

在结束由于目标C只是下用添加,呼叫者整个清理这种混乱。

其他提示

可变参数是如何实现是依赖于系统的。但是,什么是可能发生的是,自变量consecutivelyly存储在缓冲区中,即使参数可以为不同的尺寸。因此,第一个8个字节(假设这是一个long long int的大小)的参数是long long int,并在接下来的4个字节(假设这是您的系统上的指针的大小)是NSString指针。

然后当你告诉它预期的int然后指针的功能,它希望前4个字节是int(假设这是一个int的大小)和在接下来的4个字节为指针。因为在系统上的参数的特定端序和布置,前4个字节的long long int的恰好是你的电话号码的至少显著字节,所以它打印123.然后,对于该对象的指针,它读取在接下来的4个字节,其在这种情况下你的电话号码,这是所有0的最显著个字节,使其被解释为nil指针。实际指针永远不会被读取。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top