Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foundation types when compiling for arm64 and 32-bit architecture

Compiling my iOS application's code for arm64 I faced an interesting problem, related to different basic types for custom Foundation types. Say I want to printf (or stringWithFormat) a number declared as NSUInteger

[NSString stringWithFormat:@"%u", _depth,

This will produce a warning compiling for arm64, because NSUInteger declared as unsigned long for arm64. Therefore, I should replace "%u" with "%lu", but now this becomes invalid when compiling for armv7(s) architecture, because for 32-bit architectures NSUInteger declared as unsigned int. I'm aware that warning says "NSUInteger should not be used as format argument", so lets proceed to floats:

typedef CGFLOAT_TYPE CGFloat;

on 64-bit CGFLOAT_TYPE is double, while on 32-bit it is float. Therefore, doing something like this:

- (void)foo:(CGFloat)value;

and then

[self foo:10.0f]; 
[self foo:10.0]; 

Will still produce a warning when compiling for two architectures. On 32-bit architecture second call is not correct (conversion from double to float), on 64-bt architecture, the first one converts float to double (which is ok, but still not good).

Would love to hear your thoughts on this problem.

like image 280
Serhii Avatar asked Sep 17 '13 11:09

Serhii


1 Answers

One (admittedly awful) approach I've seen used is to use the magic of #define and compile time string literal concatenation. Like this:

// In your prefix header or something
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

// Then later you can use these like this...
NSString* foo = [NSString stringWithFormat:@"%"NSU" things in the array.", array.count]);

Pretty horrible, but it works.

Another, seemingly more common approach is to simply upcast the value to the larger type on every platform, like this:

NSString* foo = [NSString stringWithFormat:@"%lu things in the array.", (unsigned long)array.count]);

More recently (i.e. since the new boxing shorthand syntax came out) I've found myself being lazy and have started just boxing everything, like this:

NSString* foo = [NSString stringWithFormat:@"%@ things in the array.", @(array.count)]);

There may be a better way, but those are the ones I've seen the most.

like image 95
ipmcc Avatar answered Oct 17 '22 05:10

ipmcc