web-dev-qa-db-fra.com

Objective-C: BOOL vs bool

J'ai vu le "nouveau type" BOOL (YES, NO).

J'ai lu que ce type est presque comme un char.

Pour tester j'ai fait:

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

Il est bon de voir que les deux journaux affichent "1" (parfois, en C++, bool est un entier et sa taille est de 4)

Alors je me demandais s'il y avait des problèmes avec le type bool ou quelque chose?

Puis-je simplement utiliser bool (qui semble fonctionner) sans perdre de vitesse?

187
Francescu

De la définition dans 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)

Donc, oui, vous pouvez supposer que BOOL est un personnage. Vous pouvez utiliser le type (C99) bool, mais tous les frameworks Objective-C d’Apple et la plupart du code Objective-C/Cocoa utilisent BOOL.

194
Barry Wark

Comme mentionné ci-dessus, BOOL est un caractère signé. bool - type de C99 standard (int).

BOOL - OUI/NON bool - vrai/faux.

Voir des exemples:

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");

Et le résultat est

REAL b1
REAL b2
NOT REAL b2

Notez que bool! = BOOL. Le résultat ci-dessous est seulement NE FOIS ENCORE - REAL b2

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

Si vous voulez convertir bool en BOOL, vous devez utiliser le code suivant

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

Donc, dans notre cas:

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");

Et alors .. qu'est-ce qu'on a maintenant? :-)

33
beryllium

Au moment de la rédaction de ce document, il s'agit de la version la plus récente 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

Cela signifie que sur les appareils iOS 64 bits et sur WatchOS BOOL est exactement la même chose que bool alors que sur tous les autres appareils (OS X, iOS 32 bits), il s'agit de signed char et ne peut même pas être écrasé par le drapeau du compilateur -funsigned-char

Cela signifie également que cet exemple de code fonctionnera différemment sur différentes plates-formes (testé moi-même):

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

BTW n'assigne jamais des choses comme array.count à BOOL variable car environ 0,4% des valeurs possibles seront négatives.

11
Tobol

Le type d'Objective-C que vous devriez utiliser est BOOL. Il n'y a rien de tel qu'un type de données booléen natif, donc pour être sûr que le code compile sur tous les compilateurs, utilisez BOOL. (Il est défini dans les cadres Apple.

8
Georg Schölly

Yup, BOOL est un typedef pour un caractère signé selon objc.h.

Je ne sais pas pour bool, cependant. C'est une chose C++, non? S'il est défini comme un caractère signé où 1 correspond à OUI/vrai et 0 à NON/faux, alors j'imagine que le type que vous utilisiez importe peu.

Puisque BOOL fait partie d’Objective-C, il est probablement plus logique d’utiliser un objet BOOL pour plus de clarté (d’autres développeurs d’Objective-C pourraient être perplexes s’ils voient un booléen en cours d’utilisation).

5
Jeff

Une autre différence entre bool et BOOL est qu’ils ne convertissent pas exactement dans le même type d’objets, que vous observiez des valeurs-clés ou que vous utilisiez des méthodes telles que - [NSObject valueForKey:].

Comme tout le monde l’a dit, BOOL, c’est char. En tant que tel, il est converti en un NSNumber avec un caractère. Cet objet ne peut pas être distingué d'un NSNumber créé à partir d'un caractère normal tel que 'A' ou '\ 0'. Vous avez totalement perdu l'information selon laquelle vous aviez initialement un BOOL.

Cependant, bool est converti en CFBoolean, qui se comporte de la même manière que NSNumber, mais qui conserve l'origine booléenne de l'objet.

Je ne pense pas que ce soit un argument dans un débat BOOL vs. bool, mais cela risque de vous piquer un jour.

De manière générale, vous devriez aller avec BOOL, car c'est le type utilisé partout dans les API Cocoa/iOS (conçu avant C99 et son type bool natif).

4
Gwendal Roué

La réponse acceptée a été modifiée et son explication devient un peu incorrecte. L'échantillon de code a été actualisé, mais le texte ci-dessous reste le même. Vous ne pouvez pas supposer que BOOL est un caractère pour le moment, car cela dépend de l'architecture et de la plate-forme. Ainsi, si vous exécutez votre code sur une plate-forme 32 bits (par exemple, iPhone 5) et imprimez @encode (BOOL), vous verrez "c". Cela correspond à un type de caractère . Mais si vous exécutez votre code sur l'iPhone 5s (64 bits), vous verrez "B". Cela correspond à un type bool .

2
curious

Comme mentionné ci-dessus, BOOL pourrait être un type unsigned char en fonction de votre architecture, alors que bool est du type int. Une expérience simple montrera la différence pourquoi BOOL et bool peuvent se comporter différemment:

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);

À votre grande surprise, if(objcBOOL != YES) sera évalué à 1 par le compilateur, puisque YES est en fait le code de caractère 1, et aux yeux du compilateur, le code de caractère 64 est bien sûr pas égal au code de caractère 1 ainsi l'instruction if sera évaluée à YES/true/1 et la ligne suivante sera exécutée. Toutefois, puisqu’un type non nul bool renvoie toujours la valeur entière de 1, le problème ci-dessus n’affectera pas votre code. Voici quelques bons conseils si vous souhaitez utiliser le type Objective-C BOOL contre le type ANSI C bool:

  • Attribuez toujours la valeur YES ou NO et rien d'autre.
  • Convertissez les types BOOL à l'aide de l'opérateur double not !! afin d'éviter des résultats inattendus.
  • Lors de la vérification de YES, utilisez if(!myBool) instead of if(myBool != YES), il est beaucoup plus propre d'utiliser l'opérateur not ! et donne le résultat attendu.
1
ilgaar

Je vais contre la convention ici. Je n'aime pas les typedef à base de types. Je pense que c'est une indirection inutile qui supprime la valeur.

  1. Lorsque je vois le type de base dans votre source, je le comprends instantanément. Si c'est un typedef je dois le regarder pour voir ce que j'ai vraiment affaire.
  2. Lors du portage sur un autre compilateur ou de l'ajout d'une autre bibliothèque, leurs ensembles de types de caractères peuvent entrer en conflit et causer des problèmes difficiles à résoudre. Je viens juste d’en finir avec ce problème. Dans une bibliothèque, le type booléen était typé en int, et en mingw/gcc, il était typé.
1
Jay

Tenez également compte des différences de transtypage, en particulier lorsque vous travaillez avec des bitmasks, en raison du transtypage en caractères signés:

bool a = 0x0100;
a == true;  // expression true

BOOL b = 0x0100;
b == false; // expression true on !((TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH), e.g. MacOS
b == true;  // expression true on (TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH

Si BOOL est un caractère signé au lieu d'un booléen, la conversion de 0x0100 en BOOL supprime simplement le bit défini et la valeur résultante est 0.

0
michaf