NSInteger 的 NSLog/printf 说明符?

发布于 2024-10-06 19:02:29 字数 841 浏览 0 评论 0原文

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

A NSInteger is 32 bits on 32-bit platforms, and 64 bits on 64-bit platforms. Is there a NSLog specifier that always matches the size of NSInteger?

Setup

  • Xcode 3.2.5
  • llvm 1.6 compiler (this is important; gcc doesn't do this)
  • GCC_WARN_TYPECHECK_CALLS_TO_PRINTF turned on

That's causing me some grief here:

#import <Foundation/Foundation.h>

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

For 32 bit code, I need the %d specifier. But if I use the %d specifier, I get a warning when compiling for 64 bit suggesting I use %ld instead.

If I use %ld to match the 64 bit size, when compiling for 32 bit code I get a warning suggesting I use %d instead.

How do I fix both warnings at once? Is there a specifier I can use that works on either?

This also impacts [NSString stringWithFormat:] and [[NSString alloc] initWithFormat:].

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烧了回忆取暖 2024-10-13 19:02:29

更新的答案:

您可以使用 zt 修饰符来处理 NSIntegerNSUInteger 而不会发出警告,所有架构。

您希望使用 %zd 表示有符号,%tu 表示无符号,使用 %tx 表示十六进制。

此信息由 Greg Parker 提供。


原始答案:

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

Updated answer:

You can make use of the z and t modifiers to handle NSInteger and NSUInteger without warnings, on all architectures.

You want to use %zd for signed, %tu for unsigned, and %tx for hex.

This information comes courtesy of Greg Parker.


Original answer:

The official recommended approach is to use %ld as your specifier, and to cast the actual argument to a long.

菊凝晚露 2024-10-13 19:02:29

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

格式 %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。

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

The accepted answer is absolutely reasonable, it is standard conforming, and correct. The only problem is that it doesn't work anymore, which is completely Apple's fault.

The format %zd is the C/C++ standard format for size_t and ssize_t. Like NSInteger and NSUInteger, size_t and ssize_t are 32 bit on a 32 bit system, and 64 bit on a 64 bit system. And that's why printing NSInteger and NSUInteger using %zd worked.

However, NSInteger and NSUInteger are defined as "long" on a 64 bit system, and as "int" on a 32 bit system (which is 64 vs 32 bit). Today, size_t is defined on "long" on all systems, which is the same size as NSInteger (either 64 or 32 bit), but a different type. Either Apple's warnings have changed (so it doesn't allow passing the wrong type to printf, even though it has the right number of bits), or the underlying types for size_t and ssize_t have changed. I don't know which one, but %zd stopped working some time ago. There is no format today that will print NSInteger without warning on both 32 and 64 bit systems.

So the only thing you can do unfortunately: Use %ld, and cast your values from NSInteger to long, or from NSUInteger to unsigned long.

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

枉心 2024-10-13 19:02:29

格式化程序来自标准 UNIX/POSIX printf 函数。使用%lu表示unsigned 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 位。否则每次编译都会产生一个单独的警告。

The formatters come from the standard UNIX/POSIX printf function. Use %lu for unsigned long, %ld for long, %lld for long long, and %llu for unsigned long long. Try man printf on the console, but on Mac it is incomplete. The linux manpages are more explicit http://www.manpages.info/linux/sprintf.3.html

Both warnings can only be fixed by NSLog(@"%lu", (unsigned long)arg); combined with a cast as the code will be compiled in 32 AND 64 bit for iOS. Otherwise each compilation creates a separate warning.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文