2009-02-12 15 views
181

Widziałem "nowy typ" BOOL (YES, NO).Cel-C: BOOL kontra bool

Przeczytałem, że ten typ jest prawie jak char.

Do testów zrobiłem:

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

Dobrze widzieć, że oba dzienniki wyświetli "1" (czasami w C++ bool jest int i jego sizeof jest 4)

Więc Zastanawiam się, czy było kilka problemów z typem bool czy coś takiego?

Czy mogę po prostu użyć Bool (który wydaje się działać) bez utraty prędkości?

Odpowiedz

187

z definicji w 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) 

Tak, tak, można założyć, że BOOL jest char można użyć (C99) bool typ, ale wszystkie z frameworków Objective-C firmy Apple i większość kodu Objective-C/Cocoa używa BOOL, więc zaoszczędzisz sobie bólu głowy, jeśli typedef zmienia się tylko za pomocą BOOL:

+16

"wszystkie frameworki Apple'a" - nieprawda. Przyjrzeć CGGeometry.h, w szczególności: CG_INLINE BOOL __CGPointEqualToPoint (CGPoint punktem 1, CGPoint punkt2) { powrotu point1.x == point2.x && point1.y == point2.y; } – Elliot

+56

@ Elliot Masz rację. Wiele frameworków C (CoreFoundation, CoreGraphics itp.) Używa C99 'bool'. Wszystkie struktury Objective-C używają 'BOOL'. –

+3

wszystkie jabłka framework-c –

5

Tak, BOOL jest typedef dla podpisanego znaku według objc.h.

Nie wiem jednak, bool. To jest C++, prawda? Jeśli jest zdefiniowany jako podpis char, gdzie 1 to TAK/prawda, a 0 to NIE/fałsz, to wyobrażam sobie, że nie ma znaczenia, którego z nich używasz.

Ponieważ BOOL jest częścią Objective-C, prawdopodobnie bardziej sensowne będzie użycie BOOL-a dla jasności (inni twórcy C-ów mogą być zdziwieni, jeśli zobaczą bool w użyciu).

+6

_Bool jest zdefiniowany w C99, aw standardowym nagłówku stdbool.h zdefiniowano makro bool (który rozwija się do _Bool), a także true/false. –

8

Typem obiektu typu C, którego powinieneś użyć, jest BOOL. Nie ma to jak natywny boolowski typ danych, dlatego aby mieć pewność, że kod kompiluje się na wszystkich kompilatorach, używa się BOOL. (Jest to określone w Apple ram

+2

To nie jest ściśle dokładne. 'BOOL' jest definiowany przez język Objective-C (znajduje się w jednym z nagłówków' objc/*. H'), a nie w frameworkach. Również podczas kompilacji z C99 (co moim zdaniem jest domyślne), istnieje natywny typ Boolean, '_Bool' (lub' bool', jeśli włączono 'stdbool.h'). – dreamlax

2

Nie zgadzam się z konwencją. typedefs do typów bazowych. Myślę, że jest to bezużyteczny kierunek, który usuwa wartość.

  1. Gdy zobaczę typ bazy w Twoim źródle, natychmiast to zrozumiem. Jeśli jest to typedef, muszę sprawdzić, co tak naprawdę mam do czynienia.
  2. Podczas przenoszenia do innego kompilatora lub dodawania innej biblioteki ich zestaw typów może powodować konflikt i powodować problemy, które są trudne do debugowania. Właśnie skończyłem sobie z tym poradzić. W jednej bibliotece wartość boolowska została wpisana w int, aw mingw/gcc została przypisana do char.
+4

No cóż ... możesz * można * oczekiwać, że znasz standardowy typedef twojego języka (pomyśl o 'size_t'), a oba' bool' (C99) i 'BOOL' (ObjC) należą do tej kategorii.A jeśli twój kod nie powiodł się z powodu zmiany typedef, to twój kod jest winny, ponieważ najwyraźniej nie traktowałeś typedef jako czegoś nieprzejrzystego, ale polegałeś na jego implementacji na jednej platformie. (Nie ma się czego wstydzić, zdarza się, ale nie jest to wina typowania). – DevSolar

+1

"Standardowe" typy nie wydają się być bardzo standardowe (na przykład przez pewien czas MS nie obsługiwały standardów posix itp.). Jeśli nie używasz typedefs, eliminowany jest problem z zamianą lub byciem innym na różnych kompilatorach. – Jay

+1

-1, typedefs ogólnie służą dwóm ważnym celom (między innymi): zapewniają dobrą semantykę i zapewniają pewne błędne ukierunkowanie. Idealnie nie powinieneś znać podstawowego typu, do którego odnosi się typedef, niestety ten system nie jest doskonały i czasami musisz go znać. Chodzi mi o to, że powinieneś postępować zgodnie z konwencją, ponieważ nawet przyznając, że nie jest ona doskonała, jest lepsza niż alternatywa. –

32

Jak wspomniano powyżej, BOOL jest znakiem char. bool - typ od standardu C99 (int).

BOOL - TAK/NIE. bool - true/false.

Zobacz przykłady:

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

A wynik jest

NIERUCHOMOŚCI b1
NIERUCHOMOŚCI b2
nie real b2

Zauważ, że bool = BOOL!. Wynik poniżej jest tylko ONCE AGAIN - real b2

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

Jeśli chcesz przekonwertować bool do BOOL należy użyć kolejnego kodu

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

Tak, w naszym przypadku:

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

A więc ... co mamy teraz? :-)

+3

Można zamiast używać potrójnego operatora użyć '!! b1'. Aby przekonwertować między nimi –

+0

"NOT REAL b2" nie jest drukowane na moim symulatorze iPhone SE. – gabbler

4

Kolejną różnicą między BOOL i BOOL jest to, że nie konwertują dokładnie tego samego rodzaju obiektów, gdy obserwujesz parę klucz-wartość lub gdy używasz metod takich jak - [NSObject valueForKey:].

Jak wszyscy tu mówili, BOOL jest char. Jako taki, jest konwertowany na NSNumber trzymający char. Ten obiekt jest nie do odróżnienia od NSNumber utworzonego z regularnego znaku "A" lub "\ 0". Całkowicie zgubiłeś informację, że pierwotnie miałeś BOOL.

Jednak bool jest konwertowany na CFBoolean, który zachowuje się tak samo jak NSNumber, ale zachowuje boolowskie pochodzenie obiektu.

Nie sądzę, że jest to argument w debacie BOOL przeciwko boolowi, ale to może cię kiedyś ugryźć.

Ogólnie rzecz biorąc, powinieneś wybrać z BOOL, ponieważ jest to typ używany wszędzie w interfejsach API Cocoa/iOS (zaprojektowany przed C99 i jego natywnym typem bool).

9

W chwili pisania tego jest najnowsza wersja 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 

Oznacza to, że w 64-bitowych urządzeń iOS i na WatchOS BOOL jest dokładnie to samo, co bool czas na wszystko inne urządzenia (OS X, 32-bitowy iOS) jest signed char i nie może nawet być przesłonięte przez flag kompilatora -funsigned-char

oznacza to również, że ten przykładowy kod będzie działać w różny sposób na różnych platformach (testowane to sam):

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

BTW nigdy nie przypisuj zmiennych takich jak array.count do BOOL, ponieważ około 0,4% możliwych wartości będzie ujemnych.

2

Przyjęta odpowiedź została zmieniona, a jej objaśnienie stało się nieco niepoprawne. Próbka kodu została odświeżona, ale tekst poniżej pozostaje taki sam. Nie można zakładać, że BOOL jest na razie char, ponieważ zależy to od architektury i platformy. Tak więc, jeśli uruchomisz kod na platformie 32-bitowej (na przykład iPhone 5) i print @ kodode (BOOL), zobaczysz "c". Odpowiada to char type. Ale jeśli uruchomisz kod na iPhone 5s (64-bitowy), zobaczysz "B". Odpowiada to bool type.

1

Jak wspomniano powyżej BOOL może być typ unsigned char zależności od architektury, a bool jest typu int. Prosty eksperyment pokaże różnicę dlaczego BOOL i bool mogą zachowywać się różnie:

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

do swojego zaskoczenia if(objcBOOL != YES) wola ocenia na 1 przez kompilator, ponieważ YES jest rzeczywiście znakowy kod 1, a w oczach kompilatora, kod znaku 64 to oczywiście nie jest równy dla kodu postaci 1 tym samym instrukcja if będzie oznaczać YES/true/1 i zostanie uruchomiona następująca linia. Jednak ponieważ typ zero zero bool zawsze zwraca wartość całkowitą równą 1, powyższy problem nie wpłynie na kod. Poniżej znajduje się kilka dobrych wskazówek, jeśli chcesz użyć typu Objective-C BOOL vs typu ANSI C bool:

  • Zawsze przypisać wartość i nic innego YES lub NO.
  • Konwertuj typy BOOL, używając operatora podwójnego nie !!, aby uniknąć nieoczekiwanych wyników.
  • Podczas sprawdzania YES użyj if(!myBool) instead of if(myBool != YES) jest znacznie czystsze używać operatora nie ! i daje oczekiwany wynik.