Sự khác biệt giữa sử dụng CGFloat và float là gì?


169

Tôi có xu hướng sử dụng CGFloat ở mọi nơi, nhưng tôi tự hỏi liệu tôi có nhận được "cú đánh hiệu suất" vô nghĩa với điều này không. CGFloat dường như là một cái gì đó "nặng" hơn float, phải không? Tôi nên sử dụng CGFloat ở những điểm nào và điều gì thực sự tạo nên sự khác biệt?

Câu trả lời:


193

Như @weichsel đã nêu, CGFloat chỉ là một typedef cho một trong hai floathoặc double. Bạn có thể tự mình nhìn thấy bằng cách nhấp đúp vào "CGFloat" trong Xcode - nó sẽ nhảy đến tiêu đề CGBase.h nơi xác định typedef. Cách tiếp cận tương tự cũng được sử dụng cho NSInteger và NSUInteger.

Các loại này đã được giới thiệu để giúp viết mã dễ dàng hơn trên cả 32 bit và 64 bit mà không cần sửa đổi. Tuy nhiên, nếu tất cả những gì bạn cần là floatđộ chính xác trong mã của riêng bạn, bạn vẫn có thể sử dụng floatnếu bạn muốn - nó sẽ giảm phần nào bộ nhớ của bạn. Tương tự với các giá trị nguyên.

Tôi khuyên bạn nên đầu tư thời gian khiêm tốn cần thiết để làm cho ứng dụng của mình sạch 64 bit và thử chạy nó như vậy, vì hầu hết các máy Mac hiện có CPU 64 bit và Snow Leopard hoàn toàn 64 bit, bao gồm cả ứng dụng kernel và người dùng. Hướng dẫn chuyển đổi 64-bit cho ca cao của Apple là một tài nguyên hữu ích.


Tôi nghĩ rằng tôi nhận được nó ngay bây giờ. Nhưng trên iPhone dường như không quan trọng lắm, phải không?

4
Trên iPhone như chúng ta đã biết, không. Tuy nhiên, việc sử dụng mã chứng minh trong tương lai luôn luôn khôn ngoan và điều này sẽ giúp việc sử dụng lại mã tương tự cho OS X. dễ dàng hơn
Quinn Taylor

vì vậy, về cơ bản, bạn KHÔNG BAO GIỜ sử dụng float hoặc double trực tiếp kể từ đó bạn sẽ bị ràng buộc với kiến ​​trúc bộ xử lý (và tôi nghĩ rằng các JVM đã được giải quyết nhanh trong những năm trước :)). Vậy những gì nguyên thủy là an toàn? int?
Dan Rosenstark

9
Tôi không nói KHÔNG BAO GIỜ sử dụng trực tiếp nguyên thủy. Đôi khi các nguyên thủy thẳng có thể gặp vấn đề, chẳng hạn như nếu một biến có thể được sử dụng để lưu trữ dữ liệu có thể bị tràn, chẳng hạn như trên 64 bit. Nói chung, sử dụng typedefs phụ thuộc vào kiến ​​trúc sẽ an toàn hơn, trong đó mã ít có khả năng phát nổ trên một kiến ​​trúc khác. Tuy nhiên, đôi khi sử dụng loại 32 bit có thể hoàn toàn an toàn và giúp bạn tiết kiệm bộ nhớ. Kích thước của các nguyên hàm có thể ít gặp sự cố trong JVM, nhưng Obj-C và C được biên dịch, và việc trộn các thư viện và mã 32 và 64 bit thực sự có vấn đề.
Quinn Taylor

1
@QuinnTaylor bạn có thể cung cấp một ví dụ thực tế về việc float sẽ tràn trong khi CGFloat không? Cả float và CGFloat đều có số bit hữu hạn. Bạn có thể tràn cả hai bằng cách cần lưu trữ nhiều bit hơn mức chúng có thể giữ.
Pwner 24/2/2015

76

CGFloat là một float thông thường trên các hệ thống 32 bit và gấp đôi trên các hệ thống 64 bit

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

Vì vậy, bạn sẽ không nhận được bất kỳ hình phạt hiệu suất.


3
Chà, bạn sử dụng gấp đôi bộ nhớ, nếu bạn lo lắng về bộ nhớ.
Tyler

8
Chỉ trên 64-bit, mặc dù.
Quinn Taylor

13
Đúng, hệ điều hành iPhone là 32 bit. Nếu bạn nghĩ về nó, iPhone không đẩy giới hạn RAM 4GB là 32 bit, cũng không sử dụng bộ xử lý Intel (trong đó 64 bit nhanh hơn 32 bit). Ngoài ra, đó là sử dụng Modern Runtime (trái ngược với Legacy Runtime 32 bit trên máy tính để bàn - hãy tìm kiếm SO cho các thuật ngữ này nếu bạn tò mò) để nó có thể làm mọi thứ về cơ bản mọi thứ OS X 64 bit. Có lẽ một ngày nào đó chúng ta sẽ thấy một thiết bị chạy HĐH iPhone và 64-bit, nhưng hiện tại không có thiết bị nào.
Quinn Taylor

23
Nhập: iPhone 5S
dgund

7
5S bây giờ là 64 bit, lần trước khi tôi tham gia hội nghị (london), họ nói rằng cách họ chạy các ứng dụng 32 bit trên ios7 là để khởi tạo một nhóm bộ nhớ cache chia sẻ khác trong bộ nhớ, có thể dẫn đến việc sử dụng nhiều bộ nhớ hơn. vì vậy def của nó có giá trị để chuyển đổi mọi thứ lên đến 64 bit. (trừ khi bạn muốn hỗ trợ 5.1+ hoặc 6.0+ vẫn còn)
phil88530

2

Như những người khác đã nói, CGFloat là một hệ số nổi trên hệ thống 32 bit và gấp đôi trên hệ thống 64 bit. Tuy nhiên, quyết định thực hiện điều đó được kế thừa từ OS X, nơi nó được đưa ra dựa trên các đặc tính hiệu năng của CPU PowerPC đời đầu. Nói cách khác, bạn không nên nghĩ rằng float là dành cho CPU 32 bit và double là cho CPU 64 bit. . .


2

Mục tiêu-C

Từ mã nguồn Foundation, trong 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

Bản quyền (c) 2000-2011 Apple Inc.

Điều này về cơ bản là làm:

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

Trong đó __LP64__cho biết kiến ​​trúc hiện tại * là 64 bit.

Lưu ý rằng các hệ thống 32 bit vẫn có thể sử dụng 64 bit double, nó chỉ mất nhiều thời gian xử lý hơn, vì vậy CoreGraphics thực hiện điều này cho mục đích tối ưu hóa, không phải để tương thích. Nếu bạn không quan tâm đến hiệu suất nhưng lo ngại về độ chính xác, chỉ cần sử dụng double.

Nhanh

Trong Swift, CGFloatlà mộtstruct trình bao bọc xung quanh Floattrên các kiến ​​trúc 32 bit hoặc Doubletrên các cấu trúc 64 bit (Bạn có thể phát hiện điều này trong thời gian chạy hoặc biên dịch với CGFloat.NativeType)

Từ mã nguồn CoreGraphics, trongCGFloat.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

* Cụ thể, longs và con trỏ, do đó LP. Xem thêm: http://www.unix.org/version2/whatsnew/lp64_wp.html


1

chỉ cần đề cập đến điều đó - Tháng 1, 2020 Xcode 11.3 / iOS13

Swift 5

Từ mã nguồn 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.