Яка різниця між використанням CGFloat та float?


169

Я, як правило, використовую CGFloat всюди, але мені цікаво, чи отримую з цього безглуздий "ударний показник". CGFloat здається чимось "важчим", ніж float, правда? У яких моментах я повинен використовувати CGFloat, і що насправді має різницю?

Відповіді:


193

Як зазначає @weichsel, CGFloat - це лише typedef для будь-якого floatабо double. Ви можете переконатися в тому, що двічі клацніть на команді "CGFloat" у Xcode - вона перейде до заголовка CGBase.h, де визначено typedef. Один і той же підхід використовується і для NSInteger та NSUInteger.

Ці типи були введені для полегшення запису коду, який працює як на 32-розрядному, так і на 64-розрядному без змін. Однак якщо все, що вам потрібно, - це floatточність у вашому власному коді, ви все одно можете використовувати, floatякщо вам подобається - це дещо зменшить слід вашої пам’яті. Те саме стосується цілих значень.

Я пропоную вам вкласти скромний час, необхідний для того, щоб зробити ваш додаток 64-бітним чистим, і спробувати запустити його як таке, оскільки більшість Macs зараз мають 64-розрядні процесори, а Snow Leopard повністю 64-бітний, включаючи ядро ​​та користувацькі програми. 64-бітний посібник з переходу Apple на какао - корисний ресурс.


Я думаю, я зараз це зрозумію. Але на iPhone це, здається, не має великого значення, правда?

4
На iPhone, як ми його знаємо, немає. Однак, завжди розумно використовувати захищений від майбутнього код, і це полегшить безпечне використання того ж коду для ОС X.
Квінн Тейлор,

так що ви говорите, в основному, НІКОЛИ не використовуйте поплавок або подвійний безпосередньо з тих пір, ви були б прив'язані до архітектури процесора (і я думав, швидкі JVM, вирішені в цьому роки тому :)). То які примітиви безпечні? int?
Дан Розенстарк

9
Я не сказав, що НІКОЛИ не використовуйте примітиву безпосередньо. Бувають випадки, що прямі примітиви можуть бути проблематичними, наприклад, якщо змінна може бути використана для зберігання даних, які можуть переповнюватися, наприклад, на 64-розрядному. Взагалі, використання типів, що залежать від архітектури, є більш безпечним, оскільки цей код менше шансів вибухнути в іншій архітектурі. Однак іноді використання 32-бітного типу може бути повністю безпечним та заощадити пам’ять. Розмір примітивів може бути меншим питанням у JVM, але Obj-C і C складаються, і змішування 32 та 64 бітових бібліотек та коду справді проблематично.
Квінн Тейлор

1
@QuinnTaylor Ви можете надати практичний приклад того, як float переповнюється, тоді як CGFloat не буде? І float, і CGFloat мають кінцеву кількість бітів. Ви можете переповнювати їх обох, потрібно зберігати більше бітів, ніж вони вміщають.
Pwner

76

CGFloat є звичайним плаваючим на 32-бітних системах і подвійним на 64-бітних системах

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

Таким чином, ви не отримаєте жодного штрафу за продуктивність.


3
Ну, ви використовуєте вдвічі більше пам’яті, якщо турбуєтесь про пам’ять.
Тайлер

8
Тільки на 64-розрядному.
Квінн Тейлор

13
Правильно, операційна система iPhone 32-бітна. Якщо ви подумаєте над цим, iPhone не натискає на 32 ГБ обмеження оперативної пам’яті на 4 ГБ, а також не використовує процесор Intel (для якого 64-бітний швидше, ніж 32-розрядний). Крім того, він використовує Modern Runtime (на відміну від Legacy Runtime 32-розрядного на робочому столі - дивіться ТА за цими умовами, якщо вам цікаво), тому він може робити в основному все, що може мати 64-розрядна ОС X. Можливо, колись ми побачимо пристрій, який працює під управлінням ОС iPhone і 64-розрядний, але наразі його немає.
Квінн Тейлор

23
Введіть: iPhone 5S
dgund

7
5S зараз у 64-бітному, останній раз, коли я входив на конференцію (Лондон), вони сказали, що спосіб запуску 32-розрядних додатків на ios7 - це запустити інший спільний кеш-пул у пам'яті, що може призвести до використання загальної кількості пам'яті. тому його def варто перетворити все на 64-бітні. (якщо ви ще не хочете підтримувати 5.1+ або 6.0+)
phil88530

2

Як вже говорили інші, CGFloat - це плаваючий на 32-бітних системах і подвійний на 64-бітних системах. Однак рішення зробити це було успадковано від OS X, де воно було прийняте на основі експлуатаційних характеристик ранніх процесорів PowerPC. Іншими словами, ви не повинні думати, що float призначений для 32-бітних процесорів, а подвійний - для 64-бітних процесорів. (Я вважаю, що ARM-процесори Apple змогли обробити парні задовго до того, як вони вийшли 64-бітними.) Основний хіт при використанні парних пар - це те, що вони використовують вдвічі більше пам’яті і тому можуть бути повільнішими, якщо ви робите багато операцій з плаваючою комою. .


2

Ціль-С

З вихідного коду фонду в 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є structобгортка навколо Float32-розрядної архітектури або Double64-бітової (Ви можете виявити це під час виконання або компіляції за допомогою CGFloat.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 р. 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.