“NSString stringWithFormat:”在 32 位设备中具有“%zd”奇怪行为
Posted
技术标签:
【中文标题】“NSString stringWithFormat:”在 32 位设备中具有“%zd”奇怪行为【英文标题】:"NSString stringWithFormat:" with "%zd" curious behavior in 32bit devices 【发布时间】:2017-09-12 10:01:21 【问题描述】:为什么我们无法在 32 位设备(iPhone5、iPhone4s 或其模拟器)中按预期使用“%zd”格式化字符串?
int64_t test1 = 11111111;
int64_t test2 = 22222222;
int64_t test3 = 33333333;
int64_t test4 = 44444444;
NSString *testStr = [NSString stringWithFormat:@"\"%zd %zd %zd %zd\"", test1, test2, test3, test4];
NSLog(@"testStr: %@", testStr);
NSInteger test5 = 55555555;
NSInteger test6 = 66666666;
NSInteger test7 = 77777777;
NSInteger test8 = 88888888;
testStr = [NSString stringWithFormat:@"\"%zd %zd %zd %zd\"", test5, test6, test7, test8];
NSLog(@"testStr: %@", testStr);
日志是:
2017-09-12 05:53:59.462: testStr:"11111111 0 22222222 0"
2017-09-12 05:53:59.465: testStr:"55555555 66666666 77777777 88888888"
【问题讨论】:
【参考方案1】:注意:答案只是在平板电脑上输入的,您的样本没有经过测试,所以这是一个猜测。
%zd
格式适用于 size_t
类型的值,而不是 64 位值。
尝试将%lld
用于int64_t
值,long long
在 32 位和 64 位 ios 版本上都是 64 位。
对于NSInteger
尝试%ld
并将参数转换为long
,这是因为NSInteger
的大小取决于平台。
HTH
【讨论】:
想你的回复。抱歉回复慢。我知道你说什么,而且你的回答是对的。但我还是不知道为什么行为如此神秘(看第一个输出)。 当参数被传递给一个变量参数函数/方法时,例如stringWithFormat:
每个参数值的字节被放置在堆栈上连续地。变量test1
是64位的,所以8个字节放在栈上,这些后面跟着test2
的8个字节等等。在32位上%zd
格式化一个32位的值,所以对于在格式字符串中每次出现%zd
都会使用堆栈外的 4 个字节。当十进制值11111111
写为 64 位二进制数时,前 32 位全部为0
。所以test1
的 8 字节被格式化为两个 4 字节的值,第二个是0
。
听起来很合理!非常感谢你。而且,我在哪里可以学到这个?这是我不知道的有趣知识。
求知总是好的!您可以研究的两个来源:您可以调查您正在使用的编译器/cpu/OS 的 ABI;您可以在一本关于编译器的书中了解代码生成。例如,Aho & Ullman 的经典 Compilers,又名 Dragon Book,描述了调用序列,并提到了可变参数函数,例如 C 的 printf()
,尽管它是十多年前出版的它按照计算机科学标准已经“过时”了! ;-)
感谢您为我指出正确的方向。很荣幸为您提供出色的答案。以上是关于“NSString stringWithFormat:”在 32 位设备中具有“%zd”奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章