Why does an NSInteger variable have to be cast to long when used as a format argument?

后端 未结 5 1103
借酒劲吻你
借酒劲吻你 2020-12-02 06:56
NSInteger myInt = 1804809223;
NSLog(@\"%i\", myInt); <==== 

The code above produces an error:

Values of type \'NSInteger\

相关标签:
5条回答
  • 2020-12-02 07:16

    You don't have to cast to anything if your format specifiers match your data types. See Martin R's answer for details on how NSInteger is defined in terms of native types.

    So for code intended to be built for 64-bit environments, you can write your log statements like this:

    NSLog(@"%ld",  myInt); 
    

    while for 32-bit environments you can write:

    NSLog(@"%d",  myInt); 
    

    and it will all work without casts.

    One reason to use casts anyway is that good code tends to be ported across platforms, and if you cast your variables explicitly it will compile cleanly on both 32 and 64 bit:

    NSLog(@"%ld",  (long)myInt);
    

    And notice this is true not just for NSLog statements, which are just debugging aids after all, but also for [NSString stringWithFormat:] and the various derived messages, which are legitimate elements of production code.

    0 讨论(0)
  • 2020-12-02 07:19

    It keeps warning while using NSLog(@"%ld", (long)myInt);, but stops warning after change declaration to long myInt = 1804809223; in iOS 10.

    0 讨论(0)
  • 2020-12-02 07:27

    You get this warning if you compile on OS X (64-bit), because on that platform NSInteger is defined as long and is a 64-bit integer. The %i format, on the other hand, is for int, which is 32-bit. So the format and the actual parameter do not match in size.

    Since NSInteger is 32-bit or 64-bit, depending on the platform, the compiler recommends to add a cast to long generally.

    Update: Since iOS 7 supports 64-bit now as well, you can get the same warning when compiling for iOS.

    0 讨论(0)
  • 2020-12-02 07:27

    OS X uses several data types—NSInteger, NSUInteger,CGFloat, and CFIndex—to provide a consistent means of representing values in 32- and 64-bit environments. In a 32-bit environment, NSInteger and NSUInteger are defined as int and unsigned int, respectively. In 64-bit environments, NSInteger and NSUInteger are defined as long and unsigned long, respectively. To avoid the need to use different printf-style type specifiers depending on the platform, you can use the specifiers shown in this link for both 32 bit and 64 bit environment.

    0 讨论(0)
  • 2020-12-02 07:30

    Instead of passing an NSInteger to NSLog, just pass an NSNumber. This will get around all the casts and choosing the right string format specifier.

    NSNumber foo = @9000;
    NSLog(@"foo: %@", foo);
    NSInteger bar = 9001;
    NSLog(@"bar: %@", @(bar));
    

    It also works for NSUIntegers without having to worry about that. See answer to NSInteger and NSUInteger in a mixed 64bit / 32bit environment

    0 讨论(0)
提交回复
热议问题