NSUInteger不应该用于格式字符串?

Mau*_*itz 40 objective-c

这是我的代码所有的荣耀:

[NSString stringWithFormat:@"Total Properties: %d", (int)[inArray count]];
Run Code Online (Sandbox Code Playgroud)

这给我一个Xcode 5.1警告:

Values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead
Run Code Online (Sandbox Code Playgroud)

好的,我很困惑.该值实际上是一个32位的int,我把它转换为32位int.那么这个NSUInteger抱怨的是什么(我假设的数量)以及为什么这个演员没有修复呢?

mat*_*att 94

NSUInteger和NSInteger在32位(int)和64位(long)上的长度不同.为了使一个格式说明符适用于这两种体系结构,必须使用long说明符并将值转换为long:

Type    Format Specifier    Cast
----    ----------------    ----
NSInteger    %ld            long
NSUInteger   %lu            unsigned long
Run Code Online (Sandbox Code Playgroud)

因此,例如,您的代码变为:

[NSString stringWithFormat:@"Total Properties: %lu", (unsigned long)[inArray count]];
Run Code Online (Sandbox Code Playgroud)

实际上,很少有工作要做,因为Xcode的Fix-It功能会自动为您完成.


Nic*_*ood 45

也可以将"z"和"t"修饰符用于与CPU无关的格式字符串,例如

NSInteger x = -1;
NSUInteger y = 99;
NSString *foo = [NSString stringWithFormat:@"NSInteger: %zd, NSUInteger: %tu", x, y];
Run Code Online (Sandbox Code Playgroud)


das*_*ght 8

NSUInteger基于平台的基础更改类型:它是32位平台上的32位无符号整数,以及64位平台上的64位无符号整数.

在" 字符串编程指南"的" 平台依赖关系"部分中, Apple建议您执行以下操作:

为了避免根据平台使用不同的printf样式类型说明符,可以使用表3中显示的说明符.请注意,在某些情况下,您可能必须转换值.

对于NSUInteger使用的格式%lu或者%lx,投价值unsigned long.

因此,您的代码需要按如下方式更改以避免警告:

[NSString stringWithFormat:@"Total Properties: %lu", (unsigned long)[inArray count]];
Run Code Online (Sandbox Code Playgroud)

  • @ user102008这是巧合.`NSUInteger`和`unsigned long`的大小由不同的实体(Cocoa库的制造者与Objective-C编译器的制造者)控制.`%lu`保证始终匹配`unsigned long`; "NSUInteger"没有这样的保证,因为它由不同的人拥有.如果Cocoa制造商明天决定从下一个版本开始,所有平台上的"NSUinteger"应该是32位,那么他们可以100%做到.这将破坏格式化代码而不进行强制转换. (2认同)