使用 CGFloat 和 float 有什么区别?

我倾向于在所有地方使用 CGFloat,但是我想知道我是否会得到一个无意义的“性能命中”。CGFloat 似乎是比 float 更“重”的东西,对吗?我应该在哪些时候使用 CGFloat,到底是什么造成了这种差异?

106161 次浏览

CGFloat 是32位系统上的常规 float 和64位系统上的一个替身

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

所以你不会受到任何性能处罚。

如@weichsel 所述,CGFloat 只是 floatdouble的 typedef。您可以通过 Command-双击 Xcode 中的“ CGFloat”ー它将跳转到定义 typedef 的 CGBase.h 头部。NSInteger 和 NSUInteger 也使用同样的方法。

引入这些类型是为了更容易编写不经修改即可在32位和64位上工作的代码。但是,如果您只需要在自己的代码中使用 float精度,那么您仍然可以使用 floatーー这将在一定程度上减少您的内存占用。整数值也是如此。

我建议你投入适当的时间使你的应用程序64位干净,并尝试运行这样,因为大多数 Mac 现在有64位 CPU 和雪豹是完全64位,包括内核和用户应用程序。苹果的 64位可可转换指南是一种有用的资源。

正如其他人所说,CGFloat 在32位系统上是浮点数,在64位系统上是浮点数。然而,这样做的决定是从 OS X 继承而来的,它是基于早期 PowerPC CPU 的性能特征做出的。换句话说,您不应该认为 float 适用于32位 CPU,double 适用于64位 CPU。(我相信,早在64位处理器出现之前,苹果的 ARM 处理器就已经能够处理双倍处理了。) 使用双精度浮点运算对性能的主要影响是它们使用了两倍的内存,因此如果要执行大量的浮点运算,速度可能会更慢。

目标 C

在 CoreGraphics 的 CGBase.h中,来自 Foundation 源代码:

/* 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年苹果公司。

这实际上是在做:

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

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

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

斯威夫特

在 Swift 中,CGFloat是围绕32位体系结构上的 Float或64位体系结构上的 Doublestruct包装器(您可以在运行或编译时使用 CGFloat.NativeType检测到这一点)和 cgFloat.native

来自 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

* 确切地说,是 long和指针,因此是 LP。参见: http://www.unix.org/version2/whatsnew/lp64_wp.html

只要提到这一点——2020年1月,Xcode 11.3/iOS13

Swift 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