的NSLog(...)不正确的格式说明影响到其他变量?
-
22-07-2019 - |
题
我最近浪费约半小时跟踪在此的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
指针。实际指针永远不会被读取。