Qual é a diferença entre usar CGFloat e float?


169

Costumo usar o CGFloat por todo o lado, mas me pergunto se recebo um "desempenho insensato" com isso. O CGFloat parece ser algo "mais pesado" que o float, certo? Em que pontos devo usar o CGFloat e o que realmente faz a diferença?

Respostas:


193

Como @weichsel afirmou, CGFloat é apenas um typedef para um floatou outro double. Você pode ver por si mesmo clicando duas vezes em Command em "CGFloat" no Xcode - ele irá para o cabeçalho CGBase.h onde o typedef está definido. A mesma abordagem é usada para o NSInteger e o NSUInteger também.

Esses tipos foram introduzidos para facilitar a gravação de código que funciona em 32 bits e 64 bits sem modificação. No entanto, se tudo o que você precisa é de floatprecisão no seu próprio código, você ainda pode usá- floatlo, se quiser - isso reduzirá um pouco a sua pegada de memória. O mesmo vale para valores inteiros.

Sugiro que você invista o tempo modesto necessário para limpar seu aplicativo em 64 bits e tente executá-lo dessa maneira, já que a maioria dos Macs agora possui CPUs de 64 bits e o Snow Leopard é totalmente de 64 bits, incluindo o kernel e os aplicativos do usuário. O Guia de transição de 64 bits da Apple para cacau é um recurso útil.


Eu acho que entendi agora. Mas no iPhone parece não ter muita importância, certo?

4
No iPhone como a conhecemos, não. No entanto, é sempre aconselhável código de prova de futuro, e isso tornaria mais fácil reutilizar com segurança o mesmo código para OS X.
Quinn Taylor

então você está dizendo, basicamente, NUNCA use um float ou o dobro diretamente desde então, você estaria vinculado à arquitetura do processador (e eu pensei que as JVMs rápidas foram resolvidas isso anos atrás :)). Então, quais primitivos são seguros? int?
Dan Rosenstark

9
Eu não disse NUNCA usar um primitivo diretamente. Há momentos em que as primitivas diretas podem ser problemáticas, como se uma variável pudesse ser usada para armazenar dados que poderiam estourar, como em 64 bits. Em geral, o uso de typedefs dependentes da arquitetura é mais seguro, pois é menos provável que o código exploda em uma arquitetura diferente. No entanto, às vezes, usar um tipo de 32 bits pode ser completamente seguro e economizar memória. O tamanho das primitivas pode ser um problema menor em uma JVM, mas Obj-C e C são compilados e a mistura de bibliotecas e códigos de 32 e 64 bits é realmente problemática.
Quinn Taylor

1
@QuinnTaylor, você pode fornecer um exemplo prático de como o float transbordaria enquanto o CGFloat não? Tanto float quanto CGFloat possuem um número finito de bits. Você pode estourar os dois, precisando armazenar mais bits do que eles podem conter.
Pwner

76

CGFloat é um flutuador regular em sistemas de 32 bits e um duplo em sistemas de 64 bits

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

Então você não receberá nenhuma penalidade de desempenho.


3
Bem, você usa o dobro de memória, se estiver preocupado com a memória.
Tyler

8
Apenas em 64 bits, no entanto.
Quinn Taylor

13
Correto, o iPhone OS é de 32 bits. Se você pensar bem, o iPhone não está forçando a limitação de 4 GB de RAM de 32 bits, nem está usando um processador Intel (para o qual 64 bits é mais rápido que 32 bits). Além disso, ele está usando o Modern Runtime (em oposição ao Legacy Runtime de 32 bits na área de trabalho - pesquise SO para esses termos, se você estiver curioso), para que ele possa fazer basicamente tudo o que o OS X de 64 bits pode. Talvez algum dia veremos um dispositivo que executa o iPhone OS e é de 64 bits, mas atualmente não existe.
Quinn Taylor

23
Digite: the iPhone 5S
dgund

7
O 5S está agora em 64 bits, na última vez que entrei na conferência (london), eles disseram que a maneira como executam aplicativos de 32 bits no ios7 é iniciar outro pool de cache compartilhado na memória, o que pode resultar no uso de mais memória no geral. portanto, seu valor vale a pena converter tudo até 64 bits. (a menos que você queira oferecer suporte para os itens 5.1 e 6.0 ou superior)
phil88530

2

Como já foi dito, o CGFloat é flutuante em sistemas de 32 bits e duplo nos sistemas de 64 bits. No entanto, a decisão de fazer isso foi herdada do OS X, onde foi tomada com base nas características de desempenho das CPUs PowerPC anteriores. Em outras palavras, você não deve pensar que float é para CPUs de 32 bits e o dobro é para CPUs de 64 bits. (Acredito que os processadores ARM da Apple foram capazes de processar duplos muito antes de serem 64 bits.) O principal impacto no desempenho do uso de duplos é que eles usam o dobro da memória e, portanto, podem ser mais lentos se você estiver executando muitas operações de ponto flutuante .


2

Objetivo-C

No código-fonte da Foundation, em 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

Direitos autorais (c) 2000-2011 Apple Inc.

Isto está fazendo essencialmente:

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

Onde __LP64__indica se a arquitetura atual * é de 64 bits.

Observe que os sistemas de 32 bits ainda podem usar os de 64 bits double, apenas leva mais tempo do processador; portanto, o CoreGraphics faz isso para fins de otimização, não para compatibilidade. Se você não está preocupado com desempenho, mas com precisão, basta usar double.

Rápido

No Swift, CGFloatexiste um structinvólucro Floatem arquiteturas de 32 bits ou Doublede 64 bits (você pode detectar isso em tempo de execução ou compilação CGFloat.NativeType)

No código-fonte CoreGraphics, emCGFloat.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

* Especificamente, se longponteiros, daí o LP. Veja também: http://www.unix.org/version2/whatsnew/lp64_wp.html


1

apenas mencione isso - Jan, 2020 Xcode 11.3 / iOS13

Swift 5

No código-fonte 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.