“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”奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章