tba*_*tba 2 formatting stack printf objective-c nslog
我最近浪费了大约半个小时来追踪NSLog(...)中的奇怪行为:
NSString *text = @"abc";
long long num = 123;
NSLog(@"num=%lld, text=%@",num,text); //(A)
NSLog(@"num=%d, text=%@",num,text); //(B)
Run Code Online (Sandbox Code Playgroud)
行(A)打印预期的"num = 123,text = abc",但行(B)打印"num = 123,text = (null) ".
显然,打印long longwith %d是一个错误,但有人可以解释为什么它会导致text打印为null?
你刚搞砸堆栈上的内存对齐.我假设你使用最新的Apple产品和x86处理器.考虑到这些假设,您的堆栈在以下两种情况下都是如此:
| stack | first | second | +---------------------+-------+--------+ | 123 | | %d | +---------------------+ %lld +--------+ | 0 | | %@ | +---------------------+-------+--------+ | pointer to text | %@ |ignored | +---------------------+-------+--------+
在第一种情况下,你把堆栈8字节,然后4字节.并且指示NSLog从堆栈中取回12个字节(8个字节%lld,4个字节%@).
在第二种情况下,您指示NSLog首先占用4个字节(%d).由于您的变量长度为8个字节并且保持非常小的数字,因此上面的4个字节将为0.然后当NSLog尝试打印文本时,它将nil从堆栈中获取.
由于发送消息nil在Obj-C中有效,因此NSLog只会发送description:以nil获取任何内容,然后打印(null).
最后,由于Objective-C只是带有附加功能的C,调用者可以清理整个混乱.