2009-02-12 12 views
181

Vi el "nuevo tipo" BOOL (YES, NO).Objetivo-C: BOOL vs bool

He leído que este tipo es casi como un char.

Para las pruebas que hice:

NSLog(@"Size of BOOL %d", sizeof(BOOL)); 
NSLog(@"Size of bool %d", sizeof(bool)); 

Es bueno ver que los dos troncos que aparezca "1" (a veces en C bool ++ es un int y su sizeof es 4)

Así que me estaba preguntando si hubo algunos problemas con el tipo bool o algo así?

¿Puedo usar bool (que parece funcionar) sin perder velocidad?

Respuesta

187

partir de la definición de objc.h:..

#if (TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH 
typedef bool BOOL; 
#else 
typedef signed char BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used. 
#endif 

#define YES ((BOOL)1) 
#define NO ((BOOL)0) 

Así que, sí, se puede asumir que BOOL es un char Puede utilizar el (C99) bool tipo, pero todos los marcos Objective-C de Apple y la mayoría del código Objective-C/Cocoa usa BOOL, así que te ahorrarás dolores de cabeza si el typedef cambia alguna vez usando BOOL.

+16

"todos los marcos de Apple" - no es cierto. Echar un vistazo a CGGeometry.h, específicamente: CG_INLINE bool __CGPointEqualToPoint (CGPoint point1, CGPoint punto2) { retorno point1.x == == point2.x && point1.y point2.y; } – Elliot

+56

@Elliot Estás en lo correcto. Muchos de los frameworks C (CoreFoundation, CoreGraphics, etc.) usan C99 'bool'. Todos los frameworks de Objective-C usan 'BOOL'. –

+3

todas las manzanas frameworks objetivo-c –

5

Yup, BOOL es un typedef para un char firmado según objc.h.

No sé de bool, sin embargo. Eso es algo de C++, ¿verdad? Si se define como un carácter firmado donde 1 es SÍ/verdadero y 0 es NO/falso, entonces me imagino que no importa cuál use.

Dado que BOOL es parte de Objective-C, sin embargo, probablemente tenga más sentido utilizar un BOOL para mayor claridad (otros desarrolladores de Objective-C podrían quedar perplejos si ven un bool en uso).

+6

_Bool se define en C99, y en el encabezado estándar stdbool.h, se define el macro bool (que se expande a _Bool) y verdadero/falso se definen aquí también. –

8

El tipo Objective-C que debe usar es BOOL. No hay nada como un tipo de datos booleano nativo, por lo tanto, para asegurarse de que el código se compila en todos los compiladores, use BOOL. (Se define en la manzana-Marcos

+2

Esto no es estrictamente exacto. 'BOOL' se define por el lenguaje Objective-C (está en uno de los encabezados' objc/*. H'), no por los marcos. Además, cuando compilo con C99 (que creo que es el predeterminado), entonces hay un tipo booleano nativo, '_Bool' (o' bool' si se incluye 'stdbool.h'). – dreamlax

2

Voy contra la convención aquí. No me gusta typedef's a tipos básicos. Creo que es una indirección inútil que elimina el valor.

  1. Cuando veo el tipo de base en su fuente, lo entenderé al instante. Si es un typedef, tengo que buscarlo para ver a qué me refiero.
  2. Al migrar a otro compilador o agregar otra biblioteca, su conjunto de tiposdefue puede entrar en conflicto y causar problemas que son difíciles de depurar. Acabo de hacer frente a esto de hecho. En una biblioteca boolean fue typedef'ed to int, y en mingw/gcc es typedef'ed a char.
+4

Bueno ... usted * puede * esperar que conozca los typedef's estándar de su idioma (piense 'size_t'), y tanto' bool' (C99) como 'BOOL' (ObjC) entran en esa categoría.Y si su código falló debido a un cambio de typedef, es su código el culpable ya que aparentemente no manejó el typedef como una cosa opaca pero confió en su implementación en una plataforma. (No hay de qué avergonzarse, sucede, pero no es el tipo de culpable.) – DevSolar

+1

Los defs typedefs "estándar" no parecen ser muy estándar (por ejemplo, por un tiempo MS no admitió los estándares posix, etc.). Si no utiliza typedefs, entonces se elimina el problema con typedefs que cambian o que son diferentes en compiladores diferentes. – Jay

+1

-1, typedefs en general sirven dos propósitos importantes (entre otros): proporcionar una buena semántica y proporcionar una dirección equivocada. Lo ideal es que no necesites saber el tipo de base al que se refiere un typedef, desafortunadamente este sistema no es perfecto y algunas veces debes saberlo. Mi punto es: debes seguir la convención porque incluso admitir que no es perfecto es mejor que la alternativa. –

32

Como se mencionó anteriormente, BOOL es un char firmado. bool - tipo del estándar C99 (int).

BOOL - SÍ/NO. bool - verdadero/falso.

Ver ejemplos:

bool b1 = 2; 
if (b1) printf("REAL b1 \n"); 
if (b1 != true) printf("NOT REAL b1 \n"); 

BOOL b2 = 2; 
if (b2) printf("REAL b2 \n"); 
if (b2 != YES) printf("NOT REAL b2 \n"); 

Y resultado es

b1 b2 VERDADERO
VERDADERO
NO b2 VERDADERO

Tenga en cuenta que bool = BOOL!. Resultado continuación es sólo vez más - b2 VERDADERO

b2 = b1; 
if (b2) printf("ONCE AGAIN - REAL b2 \n"); 
if (b2 != true) printf("ONCE AGAIN - NOT REAL b2 \n"); 

Si desea convertir BOOL BOOL se debe utilizar junto código

BOOL b22 = b1 ? YES : NO; //and back - bool b11 = b2 ? true : false; 

Por lo tanto, en nuestro caso:

BOOL b22 = b1 ? 2 : NO; 
if (b22) printf("ONCE AGAIN MORE - REAL b22 \n"); 
if (b22 != YES) printf("ONCE AGAIN MORE- NOT REAL b22 \n"); 

Y entonces ... ¿Qué tenemos ahora? :-)

+3

Podría, en lugar de usar el operador ternario usar '!! b1'. Para convertir entre ellos –

+0

'NOT REAL b2' no está impreso en mi simulador de iPhone SE. – gabbler

4

Otra diferencia entre bool y BOOL es que no se convierten exactamente en el mismo tipo de objetos, cuando se realiza una observación de valores-clave o cuando se utilizan métodos como - [NSObject valueForKey:].

Como todos han dicho aquí, BOOL es char. Como tal, se convierte en un NSNumber que contiene un char. Este objeto es indistinguible de un NSNumber creado a partir de un carácter normal como 'A' o '\ 0'. Has perdido por completo la información de que originalmente tenías un BOOL.

Sin embargo, bool se convierte en CFBoolean, que se comporta igual que NSNumber, pero que conserva el origen booleano del objeto.

No creo que este sea un argumento en un debate BOOL vs. bool, pero esto puede morderlo algún día.

En general, debe ir con BOOL, ya que este es el tipo utilizado en todas partes en las API de Cocoa/iOS (diseñado antes de C99 y su tipo de bool nativo).

9

En el momento de escribir esto es la versión más reciente de objc.h:

/// Type to represent a boolean value. 
#if (TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH 
#define OBJC_BOOL_IS_BOOL 1 
typedef bool BOOL; 
#else 
#define OBJC_BOOL_IS_CHAR 1 
typedef signed char BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used. 
#endif 

Esto significa que en los dispositivos iOS de 64 bits y en watchos BOOL es exactamente lo mismo que bool mientras que en todo otros dispositivos (OS X, 32-bit iOS) es signed char y ni siquiera puede ser anulado por bandera compilador -funsigned-char

también significa que este ejemplo de código se ejecutará de manera diferente en diferentes plataformas (probaron yo):

int myValue = 256; 
BOOL myBool = myValue; 
if (myBool) { 
    printf("i'm 64-bit iOS"); 
} else { 
    printf("i'm 32-bit iOS"); 
} 

BTW nunca asigne cosas como array.count a BOOL variable porque aproximadamente el 0,4% de los posibles valores serán negativos.

2

La respuesta aceptada ha sido editada y su explicación es un poco incorrecta. La muestra del código se ha actualizado, pero el texto a continuación se mantiene igual. No puede suponer que BOOL es un char por ahora ya que depende de la arquitectura y la plataforma. Por lo tanto, si ejecuta el código en la plataforma de 32 bits (por ejemplo, iPhone 5) e imprime @encode (BOOL), verá "c". Corresponde a un char type. Pero si ejecuta el código en el iPhone 5s (64 bit), verá "B". Corresponde a un bool type.

1

Como se mencionó anteriormente BOOL podría ser un tipo unsigned char dependiendo de su arquitectura, mientras que bool es de tipo int. Un experimento sencillo mostrará la diferencia por eso BOOL y bool pueden comportarse de manera diferente:

bool ansicBool = 64; 
if(ansicBool != true) printf("This will not print\n"); 

printf("Any given vlaue other than 0 to ansicBool is evaluated to %i\n", ansicBool); 

BOOL objcBOOL = 64; 
if(objcBOOL != YES) printf("This might print depnding on your architecture\n"); 

printf("BOOL will keep whatever value you assign it: %i\n", objcBOOL); 

if(!objcBOOL) printf("This will not print\n"); 

printf("! operator will zero objcBOOL %i\n", !objcBOOL); 

if(!!objcBOOL) printf("!! will evaluate objcBOOL value to %i\n", !!objcBOOL); 

Para su sorpresa if(objcBOOL != YES) voluntad evalúa a 1 por el compilador, ya que YES es en realidad el código de caracteres 1, y en los ojos de compilador, el código de carácter 64 es, por supuesto, no igual a con el código de carácter 1, por lo que la instrucción if se evaluará a YES/true/1 y se ejecutará la siguiente línea. Sin embargo, dado que un tipo sin cero bool siempre evalúa al valor entero de 1, el problema anterior no afectará a su código. A continuación se presentan algunos buenos consejos si desea utilizar el tipo Objective-C BOOL vs el tipo ANSI C bool:

  • asignar siempre el valor YES o NO y nada más.
  • Convierta BOOL tipos usando el operador no doble !! para evitar resultados inesperados.
  • Al marcar YES utilice if(!myBool) instead of if(myBool != YES) es mucho más limpio utilizar el operador no ! y da el resultado esperado.