Qual è la differenza tra l'utilizzo di CGFloat e float?


169

Tendo a usare CGFloat dappertutto, ma mi chiedo se ottengo un "colpo di performance" insensato con questo. CGFloat sembra essere qualcosa di "più pesante" del galleggiante, giusto? In quali punti dovrei usare CGFloat e cosa fa davvero la differenza?

Risposte:


193

Come affermato da @weichsel, CGFloat è solo un typedef per floato double. Puoi vederlo tu stesso facendo doppio clic su Comando facendo clic su "CGFloat" in Xcode - salterà all'intestazione CGBase.h dove è definito typedef. Lo stesso approccio viene utilizzato anche per NSInteger e NSUInteger.

Questi tipi sono stati introdotti per semplificare la scrittura di codice che funziona su 32 e 64 bit senza modifiche. Tuttavia, se tutto ciò di cui hai bisogno è la floatprecisione all'interno del tuo codice, puoi comunque utilizzarlo floatse lo desideri - ridurrà in qualche modo il tuo spazio di memoria. Lo stesso vale per i valori interi.

Ti suggerisco di investire il modesto tempo necessario per rendere la tua app a 64 bit pulita e provare a eseguirla come tale, poiché la maggior parte dei Mac ora ha CPU a 64 bit e Snow Leopard è completamente a 64 bit, inclusi il kernel e le applicazioni utente. La Guida alla transizione a 64 bit di Apple per Cocoa è una risorsa utile.


Penso di averlo capito adesso. Ma su iPhone sembra non importare molto, giusto?

4
Su iPhone come lo conosciamo, no. Tuttavia, è sempre saggio un codice a prova di futuro, e questo renderebbe più semplice riutilizzare in sicurezza lo stesso codice per OS X.
Quinn Taylor,

quindi stai dicendo, fondamentalmente, MAI utilizzare un float o un double direttamente da allora saresti legato all'architettura del processore (e ho pensato che le JVM veloci fossero risolte anni fa :)). Quindi quali primitivi sono sicuri? int?
Dan Rosenstark,

9
Non ho mai detto MAI di usare direttamente una primitiva. Ci sono momenti in cui le primitive semplici possono essere problematiche, come se una variabile potesse essere concepibilmente utilizzata per archiviare dati che potrebbero traboccare, ad esempio su 64 bit. In generale, l'uso di typedef dipendenti dall'architettura è più sicuro, in quanto il codice ha meno probabilità di esplodere su un'architettura diversa. Tuttavia, a volte l'utilizzo di un tipo a 32 bit può essere completamente sicuro e consente di risparmiare memoria. La dimensione delle primitive potrebbe essere meno problematica in una JVM, ma Obj-C e C sono compilati e mescolare librerie e codice a 32 e 64 bit è effettivamente problematico.
Quinn Taylor,

1
@QuinnTaylor puoi fornire un esempio pratico di come traboccarebbe il float mentre CGFloat no? Sia float che CGFloat hanno un numero finito di bit. Puoi traboccare entrambi, avendo bisogno di memorizzare più bit di quanti ne possano contenere.
Pwner,

76

CGFloat è un float regolare su sistemi a 32 bit e un doppio su sistemi a 64 bit

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

Quindi non riceverai alcuna penalità per le prestazioni.


3
Bene, usi il doppio della memoria, se sei preoccupato per la memoria.
Tyler,

8
Solo su 64 bit, però.
Quinn Taylor,

13
Corretto, il sistema operativo iPhone è a 32 bit. Se ci pensate, l'iPhone non sta spingendo la limitazione di 4 GB di RAM a 32 bit, né utilizza un processore Intel (per cui 64 bit è più veloce di 32 bit). Inoltre, utilizza Modern Runtime (al contrario di Legacy Runtime di 32 bit sul desktop - cerca SO per questi termini se sei curioso) in modo che possa fare praticamente tutto ciò che può fare OS X a 64 bit. Forse un giorno vedremo un dispositivo che esegue iPhone OS ed è a 64 bit, ma attualmente non ce ne sono.
Quinn Taylor,

23
Inserisci: l'iPhone 5S
dgund

7
5S è ora a 64 bit, l'ultima volta che sono entrato nella conferenza (londra), hanno detto che il modo in cui eseguono app a 32 bit su iOS7 è quello di avviare un altro pool di cache condiviso in memoria, il che può comportare l'utilizzo di più memoria nel complesso. quindi vale la pena convertire tutto fino a 64 bit. (a meno che non si desideri supportare ancora 5.1+ o 6.0+)
phil88530

2

Come altri hanno già detto, CGFloat è un float su sistemi a 32 bit e un doppio su sistemi a 64 bit. Tuttavia, la decisione di farlo è stata ereditata da OS X, dove è stata presa in base alle caratteristiche prestazionali delle prime CPU PowerPC. In altre parole, non dovresti pensare che float sia per CPU a 32 bit e double sia per CPU a 64 bit. (Credo che i processori ARM di Apple siano stati in grado di elaborare i doppi molto prima che diventassero a 64 bit.) Il principale risultato in termini di prestazioni dell'uso dei doppi è che usano il doppio della memoria e quindi potrebbero essere più lenti se si eseguono molte operazioni in virgola mobile .


2

Objective-C

Dal codice sorgente della Fondazione, in 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

Copyright (c) 2000-2011 Apple Inc.

Questo sta essenzialmente facendo:

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

Dove __LP64__indica se l'architettura corrente * è a 64 bit.

Si noti che i sistemi a 32 bit possono ancora utilizzare il 64-bit double, richiede solo più tempo del processore, quindi CoreGraphics lo fa per scopi di ottimizzazione, non per compatibilità. Se non sei preoccupato per le prestazioni ma per la precisione, usa semplicemente double.

veloce

In Swift, CGFloatè un structwrapper Floatsu architetture a 32 bit o Doublesu quelle a 64 bit (è possibile rilevarlo in fase di esecuzione o di compilazione con CGFloat.NativeType)

Dal codice sorgente CoreGraphics, inCGFloat.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

* In particolare, longs e puntatori, quindi il LP. Vedi anche: http://www.unix.org/version2/whatsnew/lp64_wp.html


1

basta menzionarlo: gennaio 2020 Xcode 11.3 / iOS13

Swift 5

Dal codice sorgente 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.