NSInteger的NSLog / printf说明符?


131

A NSInteger在32位平台上为32位,在64位平台上为64位。是否有一个NSLog始终与大小匹配的说明符NSInteger

建立

  • Xcode 3.2.5
  • llvm 1.6编译器(这很重要; gcc不会这样做)
  • GCC_WARN_TYPECHECK_CALLS_TO_PRINTF 打开

这让我有些悲伤:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger i = 0;
        NSLog(@"%d", i);
    }
    return 0;
}

对于32位代码,我需要说明%d符。但是,如果使用说明%d符,则在编译64位时会收到警告,提示我%ld改用。

如果我%ld用来匹配64位大小,则在编译32位代码时会收到一条警告,提示我%d改为使用。

如何同时解决两个警告?是否有我可以使用的说明符?

这也会影响[NSString stringWithFormat:][[NSString alloc] initWithFormat:]

Answers:


296

更新的答案:

您可以使用的zt修饰处理NSInteger,并NSUInteger没有警告,在所有的架构。

您要%zd用于带符号,%tu无符号和%tx十六进制。

此信息由Greg Parker提供


原始答案:

官方推荐的方法是使用%ld为你的符,并且实际参数转换为long


6
这绝对是要走的路,但是我想我可以使用static inline NSIntToLong(NSInteger i) {return (long)i;}。这样可以避免完全禁用类型检查(即,如果i的类型发生更改)。
史蒂芬·费舍尔

3
@ steven-fisher的好主意。避免发出警告:static inline long NSIntToLong(NSInteger i) {return (long)i;}
Erik

3
您也可以创建一个NSNumber并将其记录下来。NSLog(@"%@",@(mynsint)); stackoverflow.com/questions/20355439/...
orkoden

2
@KevinBallard这应该不是一个严重的性能问题。无论如何,您都不应该在生产代码中使用大量的NSLog。如果由于某种原因必须记录很多内容,请在单独的线程上进行记录。
orkoden 2014年

4
从Xcode 9.3开始,在将NSInteger用作带有以下格式的格式参数时,会出现警告%zdValues of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
Rob MacEachern

2

接受的答案是绝对合理的,符合标准且正确。唯一的问题是它不再起作用了,这完全是苹果的错。

格式%zd是size_t和ssize_t的C / C ++标准格式。像NSInteger和NSUInteger一样,size_t和ssize_t在32位系统上为32位,在64位系统上为64位。这就是使用%zd打印NSInteger和NSUInteger起作用的原因。

但是,在64位系统上,NSInteger和NSUInteger被定义为“长”,而在32位系统(64位与32位)上,NSInteger和NSUInteger被定义为“ int”。今天,为size_t是在“长”定义在所有系统上,这相同的尺寸NSInteger的(64或32位),但是具有不同的类型。Apple的警告已更改(因此,即使其位数正确,也不允许将错误的类型传递给printf),或者size_t和ssize_t的基础类型已更改。我不知道是哪一个,但是%zd前一段时间停止了工作。有没有今天将打印NSInteger的没有在32个和64位系统的警告方式。

因此,您唯一可以做的就是:使用%ld,然后将值从NSInteger转换为long,或者将NSUInteger的值转换为unsigned long。

一旦不再为32位构建,就可以直接使用%ld,而无需任何强制转换。


0

格式器来自标准UNIX / POSIX printf函数。使用%lu表示无符号long,%ld表示long,%lld表示long long,%llu表示unsigned long long。在控制台上尝试man printf,但在Mac上不完整。linux手册页更为明确http://www.manpages.info/linux/sprintf.3.html

这两个警告只能通过NSLog(@“%lu”,(unsigned long)arg)来解决。结合强制类型转换,代码将针对iOS以32和64位进行编译。否则,每个编译都会创建一个单独的警告。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.