17

Consider the following function

CGSize CGSizeIntegral(CGSize size)
{
    return CGSizeMake(ceilf(size.width), ceilf(size.height));
}

CGSize actually consists of two CGFloats, and CGFloat's definition changes depending on the architecture:

typedef float CGFloat;// 32-bit
typedef double CGFloat;// 64-bit

So, the above code is wrong on 64-bit systems, and needs to be updated with something like

CGSize CGSizeIntegral(CGSize size)
{
#if 64_bit
    return CGSizeMake(ceil(size.width), ceil(size.height));
#else
    return CGSizeMake(ceilf(size.width), ceilf(size.height));
#endif
}

There is surely a compiler macro/constant for this (for Mac we can use INTEL_X86 for example) but I haven't been able to find this in the 64-bit transition guide.

How can I determine what architecture is being built for?

SG1
  • 2,871
  • 1
  • 29
  • 41

2 Answers2

33

To determine if you are compiling for 64-bit, use __LP64__:

#if __LP64__
    return CGSizeMake(ceil(size.width), ceil(size.height));
#else
    return CGSizeMake(ceilf(size.width), ceilf(size.height));
#endif

__LP64__ stands for "longs and pointers are 64-bit" and is architecture-neutral.

According to your transition guide it applies for iOS as well:

The compiler defines the __LP64__ macro when compiling for the 64-bit runtime.

However, the preferred way to handle your use case is to use CGFLOAT_IS_DOUBLE. There is no guarantee that __LP64__ will always mean the CGFloat is a double, but it would be guaranteed with CGFLOAT_IS_DOUBLE.

#if CGFLOAT_IS_DOUBLE
    return CGSizeMake(ceil(size.width), ceil(size.height));
#else
    return CGSizeMake(ceilf(size.width), ceilf(size.height));
#endif
Gerald
  • 23,011
  • 10
  • 73
  • 102
  • I see that in the docs now, thanks. It seems this would be correct, but at least in my own testing (simulator-only, no iPhone 5S here yet...) I'm getting the non-__LP64__ code executed even when building for 64-bit. I see references to it scattered throughout the SDK but it doesn't actually seem to be defined anywhere (which would explain the behavior). XCode 5 GM Seed. – SG1 Sep 18 '13 at 03:35
  • Xcode had not changed the architecture to include 64-bit in the actual build setting for "Architectures". – SG1 Sep 18 '13 at 04:06
  • 7
    `CGFLOAT_IS_DOUBLE` should be checked instead of `__LP64__`. – rpetrich Dec 05 '13 at 03:00
  • Quick question, if the app doesn't support arm64 and we have this check in the code, if we run on an 64bit device, it'll always execute the 32 bit version, right? Since it doesn't support 64bit, it never compiles for it, so LP64 is never defined - is that correct? – Andrew Feb 18 '14 at 13:18
  • As long as your project settings specify 32-bit only, then it will never be defined. – Gerald Feb 18 '14 at 16:17
  • @rpetrich Standard iOS definition: `#if defined(__LP64__) && __LP64__` `# define CGFLOAT_TYPE double` `# define CGFLOAT_IS_DOUBLE 1` `#else` `# define CGFLOAT_TYPE float` `# define CGFLOAT_IS_DOUBLE 0` `#endif` So you can use `#if defined(__LP64__) && __LP64__` just like apple developers. – Dmitrii Cooler May 28 '14 at 06:07
  • @DmitryCoolerov it's very possible that definition may change. – rpetrich May 28 '14 at 14:07
  • @rpetrich this is a standard that exists for several years. Not only on OSX/iOS – Dmitrii Cooler May 29 '14 at 04:55
  • 1
    Ultimately @rpetrich is correct. The definition of `__LP64__` is probably not going to change any time soon, but it IS possible that it will, so `CGFLOAT_IS_DOUBLE` is a better choice for this case. I updated my answer to reflect this. – Gerald May 29 '14 at 15:48
5

For Swift, and neglecting the OP's specific question involving CGFloats, etc., the following may be more swiftish:

  #if (arch(i386) || arch(arm))
     ....  // For 32-bit systems
  #else
     ....  // For 64-bit systems
  #endif


  #if (arch(x86_64) || arch(arm64))
     ....  // For 64-bit systems
  #endif

On the other hand, the compile-time constants discussed in the above answer are also available in Swift, if they are preferred.

This is mostly copied from here: https://stackoverflow.com/a/24869607/253938

And the Apple docs about these Swift compile-time constants is here: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html (at the very bottom of the page).

Community
  • 1
  • 1
RenniePet
  • 11,420
  • 7
  • 80
  • 106