使用CGFloat和float有什么区别?


169

我倾向于在各处使用CGFloat,但是我想知道这样做是否会给我带来毫无意义的“性能冲击”。CGFloat似乎比float更“重”,对吗?在什么时候应该使用CGFloat,什么才是真正的区别?

Answers:


193

如@weichsel所述,CGFloat只是floator 的typedef double。您可以通过在Xcode中双击“ CGFloat”来自己查看-它会跳到CGBase.h标头,其中定义了typedef。NSInteger和NSUInteger也使用相同的方法。

引入这些类型是为了使编写无需修改就可以在32位和64位上运行的代码变得更加容易。但是,如果您所需要的只是float在自己的代码中保持精确度,那么您仍然可以float根据需要使用它-它将在某种程度上减少内存占用。整数值也是如此。

我建议您花一些时间使您的应用程序保持64位清洁,然后尝试以这种方式运行它,因为大多数Mac现在都具有64位CPU,而Snow Leopard是完全64位的,包括内核和用户应用程序。苹果公司针对可可64位过渡指南是有用的资源。


我想我现在明白了。但是在iPhone上似乎没什么关系,对吗?

4
在我们所知道的iPhone上,没有。然而,它总是明智的,面向未来的代码,而这将使其更易于安全重用为OS X相同的代码
奎因·泰勒

因此,您的意思是,基本上,从那时起,切勿直接使用float或double,因为那样您就将与处理器体系结构联系在一起了(我想这是几年前解决的快速JVM :)。那么什么原语是安全的呢?int
丹·罗森斯塔克

9
我没有说过永远不要直接使用基元。有时,直基元可能会出现问题,例如,可以想象是否使用变量来存储可能溢出的数据(例如在64位上)。通常,使用依赖于体系结构的typedef更安全,因为代码不太可能在其他体系结构上爆炸。但是,有时使用32位类型可以完全安全并节省内存。在JVM中,原语的大小可能不是问题,但是Obj-C和C已编译,并且混合32位和64位库和代码的确存在问题。
奎因·泰勒

1
@QuinnTaylor您能提供一个实际的示例,说明浮动如何溢出而CGFloat不会溢出吗?float和CGFloat都有有限数量的位。您可能需要存储比它们可以容纳的位数更多的比特,从而使两者溢出。
普纳2015年

76

CGFloat是32位系统上的常规float,在64位系统上是double

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

因此您不会受到任何性能损失。


3
好吧,如果您担心内存,则使用两倍的内存。
泰勒

8
不过,仅在64位上。
奎因·泰勒

13
正确,iPhone OS是32位的。如果您考虑一下,iPhone并没有推动32位的4GB RAM限制,也没有使用Intel处理器(64位比32位更快)。另外,它使用的是Modern Runtime(而不是台式机上的32位旧版运行时-如果您好奇的话,请为这些术语编排SO),以便它基本上可以执行64位OS X的所有工作。也许有一天我们会看到运行iPhone OS且为64位的设备,但目前没有。
奎因·泰勒

23
输入:iPhone 5S
dgund

7
5S现在是64位的,上次我进入会议(伦敦)时,他们说在ios7上运行32位应用程序的方式是在内存中初始化另一个共享缓存池,这可能导致整体上使用更多的内存。因此它的定义值得将所有内容转换为64位。(除非您仍要支持5.1+或6.0+)
phil88530

2

正如其他人所说,CGFloat在32位系统上是浮点型,在64位系统上是双精度型。但是,这样做的决定是从OS X继承的,而OS X是根据早期PowerPC CPU的性能特征做出的。换句话说,您不应认为float是用于32位CPU的,double是用于64位CPU的。(我相信,Apple的ARM处理器能够在处理64位数据之前处理两倍的数据。)使用double数据的主要性能优势在于它们使用了两倍的内存,因此,如果您执行大量浮点运算,可能会变慢。 。


2

目标C

从基金会的源代码中,在CoreGraphics中CGBase.h

/* Definition of `CGFLOAT_TYPE', `CGFLOAT_IS_DOUBLE', `CGFLOAT_MIN', and
   `CGFLOAT_MAX'. */

#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
# define CGFLOAT_IS_DOUBLE 1
# define CGFLOAT_MIN DBL_MIN
# define CGFLOAT_MAX DBL_MAX
#else
# define CGFLOAT_TYPE float
# define CGFLOAT_IS_DOUBLE 0
# define CGFLOAT_MIN FLT_MIN
# define CGFLOAT_MAX FLT_MAX
#endif

/* Definition of the `CGFloat' type and `CGFLOAT_DEFINED'. */

typedef CGFLOAT_TYPE CGFloat;
#define CGFLOAT_DEFINED 1

版权所有(c)2000-2011 Apple Inc.

这实际上是在做:

#if defined(__LP64__) && __LP64__
typedef double CGFloat;
#else
typedef float CGFloat;
#endif

其中__LP64__表示当前体系结构*是否为64位。

请注意,32位系统仍可以使用64位double,这只需要花费更多的处理器时间,因此CoreGraphics这样做是出于优化目的,而不是为了兼容性。如果您不关心性能而是关心准确性,则只需使用double

迅速

在Swift中,CGFloat是32位体系结构或64 位体系结构的struct包装器(您可以在运行时或编译时使用来检测到这一点)FloatDoubleCGFloat.NativeType

从CoreGraphics源代码CGFloat.swift.gyb

public struct CGFloat {
#if arch(i386) || arch(arm)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = Float
#elseif arch(x86_64) || arch(arm64)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = Double
#endif

*特别是longs和指针,因此是LP。另请参阅:http : //www.unix.org/version2/whatsnew/lp64_wp.html


1

提一下-2020年1月Xcode 11.3 / iOS13

斯威夫特5

从CoreGraphics源代码

public struct CGFloat {
    /// The native type used to store the CGFloat, which is Float on
    /// 32-bit architectures and Double on 64-bit architectures.
    public typealias NativeType = Double
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.