Obiettivo-C: BOOL vs bool

Ho visto il “nuovo tipo” BOOL ( YES , NO ).

Ho letto che questo tipo è quasi un char.

Per i test ho fatto:

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

È bello vedere che entrambi i log mostrano “1” (a volte in C ++ bool è un int e la sua dimensione è 4)

Quindi mi stavo chiedendo se c’erano alcuni problemi con il tipo di bool o qualcosa del genere?

Posso semplicemente usare bool (che sembra funzionare) senza perdere velocità?

Dalla definizione in 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) 

Quindi, sì, puoi supporre che BOOL sia un char. Puoi usare il tipo di booling (C99), ma tutti i framework Objective-C di Apple e la maggior parte del codice Objective-C / Cocoa usano BOOL, quindi ti risparmierai mal di testa se il typedef cambia mai usando solo BOOL.

Come accennato in precedenza, BOOL è un char firmato. bool – digita dallo standard C99 (int).

BOOL – SÌ / NO. bool – vero / falso.

Vedi esempi:

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

E il risultato è

REAL b1
REAL b2
NON REAL b2

Si noti che bool! = BOOL. Il risultato qui sotto è solo ANCORA UNA VOLTA – REAL b2

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

Se vuoi convertire bool in BOOL dovresti usare il prossimo codice

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

Quindi, nel nostro 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"); 

E quindi .. cosa otteniamo ora? 🙂

Al momento della stesura questa è la versione più recente di 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 

Significa che su dispositivi iOS a 64 bit e su WatchOS BOOL è esattamente la stessa cosa di bool mentre su tutti gli altri dispositivi (OS X, iOS a 32 bit) è signed char e non può nemmeno essere sovrascritto dal flag del compilatore -funsigned-char

Significa anche che questo codice di esempio verrà eseguito in modo diverso su piattaforms diverse (testato personalmente):

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

BTW non assegna mai cose come array.count alla variabile BOOL perché circa lo 0,4% dei valori possibili sarà negativo.

Il tipo di Objective-C che dovresti usare è BOOL . Non c’è niente come un tipo di dati booleano nativo, quindi per essere sicuri che il codice compaia su tutti i compilatori usa BOOL . (È definito in Apple-Frameworks.

Yup, BOOL è un typedef per un char firmato secondo objc.h.

Però non so nulla di bool. Questa è una cosa in C ++, giusto? Se è definito come un carattere firmato dove 1 è SÌ / vero e 0 è NO / falso, allora immagino che non importa quale si utilizza.

Dato che BOOL fa parte di Objective-C, probabilmente ha più senso usare BOOL per chiarezza (altri sviluppatori di Objective-C potrebbero essere confusi se vedono un bool in uso).

Un’altra differenza tra bool e BOOL è che non si convertono esattamente nello stesso tipo di oggetti, quando si esegue l’osservazione dei valori-chiave o quando si utilizzano metodi come [[NSObject valueForKey:].

Come tutti hanno detto qui, BOOL è char. Come tale, viene convertito in un NSNumber con un carattere. Questo object è indistinguibile da un NSNumber creato da un carattere normale come “A” o “\ 0”. Hai completamente perso le informazioni che avevi in ​​origine una BOOL.

Tuttavia, bool viene convertito in un CFBoolean, che si comporta come NSNumber, ma che mantiene l’origine booleana dell’object.

Non penso che questo sia un argomento in un dibattito BOOL vs bool, ma questo potrebbe morderti un giorno.

In generale, si dovrebbe andare con BOOL, poiché questo è il tipo utilizzato ovunque nelle API Cocoa / iOS (progettato prima di C99 e il suo tipo di bool nativo).

La risposta accettata è stata modificata e la sua spiegazione diventa un po ‘errata. L’esempio di codice è stato aggiornato, ma il testo sottostante rimane lo stesso. Non puoi supporre che BOOL sia un char per ora poiché dipende dall’architettura e dalla piattaforma. Pertanto, se esegui il codice su una piattaforma a 32 bit (ad esempio iPhone 5) e print @encode (BOOL) vedrai “c”. Corrisponde a un tipo di carattere . Ma se esegui il codice su iPhone 5s (64 bit) vedrai “B”. Corrisponde a un tipo di bool .

Vado contro le convenzioni qui. Non mi piacciono i tipi typedef ai tipi base. Penso che sia un’indezione indiretta che rimuove il valore.

  1. Quando vedrò il tipo di base nella tua fonte, lo capirò immediatamente. Se si tratta di un typedef, devo cercarlo per vedere con cosa sto realmente lavorando.
  2. Quando si esegue il porting su un altro compilatore o si aggiunge un’altra libreria, il loro set di typedef potrebbe entrare in conflitto e causare problemi difficili da eseguire il debug. Ho appena finito di occuparmi di questo in effetti. In una libreria il booleano è stato tipizzato in “int” e in “mingw / gcc” è tipizzato in un file.

Come detto sopra BOOL potrebbe essere un tipo di unsigned char seconda dell’architettura, mentre bool è di tipo int . Un semplice esperimento mostrerà la differenza perché BOOL e bool possono comportarsi diversamente:

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

Con tua sorpresa if(objcBOOL != YES) valuterà 1 dal compilatore, poiché YES è in realtà il codice di carattere 1, e agli occhi del compilatore, il codice di carattere 64 non è ovviamente uguale al codice di carattere 1, quindi l’istruzione if valuterà su YES/true/1 e verrà eseguita la riga seguente. Tuttavia, poiché un valore di tipo zero zero bool sempre come valore intero di 1, il problema sopra riportato non influirà sul codice. Di seguito sono riportati alcuni suggerimenti utili se si desidera utilizzare il tipo Objective-C BOOL rispetto al tipo ANSI C bool :

  • Assegna sempre il valore YES o NO e nient’altro.
  • Converti i tipi BOOL usando il doppio no !! operatore per evitare risultati inaspettati.
  • Quando controlli YES usa if(!myBool) instead of if(myBool != YES) è molto più pulito usare il no ! operatore e dà il risultato atteso.