136

ANSInteger在 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:]

4

3 回答 3

304

更新的答案:

您可以在所有架构上使用zandt修饰符来处理NSInteger和不发出警告。NSUInteger

您想%zd用于有符号、%tu无符号和%tx十六进制。

此信息由Greg Parker提供。


原答案:

官方推荐的方法是%ld用作说明符,并将实际参数转换为long.

于 2010-12-10T02:04:39.897 回答
2

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

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

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

因此,不幸的是,您唯一可以做的事情是:使用 %ld,并将您的值从 NSInteger 转换为 long,或从 NSUInteger 转换为 unsigned long。

Once you don't build for 32 bit anymore, you can just use %ld, without any cast.

于 2019-09-22T00:19:34.083 回答
0

格式化程序来自标准的 UNIX/POSIX printf 函数。对unsigned long使用%lu ,对 long 使用%ld,对 long long 使用 %lld,对unsigned long long使用%llu。在控制台上尝试 man printf ,但在 Mac 上它是不完整的。linux 手册页更明确http://www.manpages.info/linux/sprintf.3.html

这两个警告只能通过 NSLog(@"%lu", (unsigned long)arg); 结合演员表,因为代码将为 iOS 编译为 32 位和 64 位。否则,每次编译都会创建一个单独的警告。

于 2014-12-16T11:18:10.913 回答