Amaç-C: BOOL vs bool


192

"Yeni tip" BOOL( YES, NO) gördüm .

Bu türün neredeyse bir karakter gibi olduğunu okudum.

Test için yaptım:

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

Her iki günlüğün de "1" görüntülediğini görmek güzel (bazen C ++ bool'de bir int ve bunun boyutu 4'tür)

Yani ben sadece bool tipinde bir sorun olup olmadığını merak ediyordum?

Hız kaybetmeden bool'u (işe yarıyor gibi görünüyor) kullanabilir miyim?

Yanıtlar:


199

İçindeki tanımdan 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)

Yani, evet, BOOL'un bir karakter olduğunu varsayabilirsiniz. (C99) booltürünü kullanabilirsiniz, ancak Apple'ın Objective-C çerçevelerinin tümünde ve çoğu Objective-C / Cocoa kodunda BOOL kullanılır, böylece typedef sadece BOOL'u kullanarak değişirse baş ağrısından tasarruf edersiniz.


17
"Apple'ın tüm çerçeveleri" - doğru değil. CGGeometry.h dosyasına özellikle göz atın: özellikle CG_INLINE bool __CGPointEqualToPoint (CGPoint noktası1, CGPoint noktası2) {dönüş noktası1.x == point2.x && point1.y == point2.y; }
Elliot

58
@Elliot Haklısın. C çerçevelerinin çoğu (CoreFoundation, CoreGraphics, vb.) C99 kullanır bool. Tüm Objective-C çerçeveleri kullanılır BOOL.
Barry Wark

@ Cœur BOOL kod örneği tanımını düzenlediniz, ancak aşağıdaki metin aynı kalıyor. Biraz kafa karıştırıcı ve yanlış. Cevabımı gör.
meraklı

Farklı davranışları aşağıda görebilirsiniz. NSInteger progressTime = 2;//any value NSInteger totalTime = 1;//any value BOOL success = (progressTime>=totalTime)// her zaman verir NO ama Bu (progressTime>=totalTime)değeri booltüre girdikten sonra successdoğru sonucu verir. Bu davranışı anlamıyorum. Kullanıyorum Xcode 7.xve iOSsürümü oldu 8.x. @BarryWark
Kamar Shad

34

Yukarıda belirtildiği gibi, BOOL imzalı bir karakterdir. bool - C99 standardından (int) yazın.

BOOL - EVET / HAYIR. bool - doğru / yanlış.

Örneklere bakın:

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

Ve sonuç

GERÇEK b1
GERÇEK b2
DEĞİL GERÇEK b2

Bool! = BOOL olduğuna dikkat edin. Aşağıdaki sonuç yalnızca TEKRAR TEKRAR - REAL b2

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

Bool'u BOOL'a dönüştürmek istiyorsanız sonraki kodu kullanmalısınız

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

Yani, bizim durumumuzda:

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

Ve böylece .. şimdi ne elde ediyoruz? :-)


3
Üçlü operatör kullanımını kullanmak yerine kullanabilirsiniz !!b1. Aralarında dönüştürme
Richard J. Ross III

1
İPhone SE simülatörde 'NOT REAL b2' basılmıyor.
gabbler

12

Yazma sırasında bu objc.h'nin en son sürümüdür:

/// 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

Bu, 64 bit iOS cihazlarda ve WatchOS'ta diğer tüm cihazlarda (OS X, 32 bit iOS) olduğu BOOLgibi aynı şey olduğu anlamına gelir ve derleyici bayrağı tarafından geçersiz kılınamaz ve hatta geçersiz kılınamazboolsigned char-funsigned-char

Ayrıca, bu örnek kodun farklı platformlarda farklı çalışacağı anlamına gelir (kendim test ettim):

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

BTW asla atama şeyler mi array.countetmek BOOLolası değerler 0.4 Yaklaşık% negatif olacaktır çünkü değişken.


iOS 32 bitlerini (iPhone 5C ...) derlerken BOOL (UIView animasyon blokları, örneğin) almak için tanımlanmış bir bloğun parametresi olarak bool kullanırsanız derleyici bir hata oluşturur. Kodumda her yerde C ++ bool ve BOOL
stephane k

8

Kullanmanız gereken Objective-C türü BOOL. Yerel bir boolean veri türü gibi bir şey yoktur, bu nedenle kodun tüm derleyicilerde derlendiğinden emin olmak için BOOL. (Apple-Frameworks'de tanımlanmıştır.


2
Bu kesinlikle doğru değil. çerçeveler tarafından değil BOOL, Objective-C dili ( objc/*.hbaşlıklardan birinde bulunur ) ile tanımlanır. Ayrıca, C99 ile derlerken (varsayılan olduğunu düşünüyorum), o zaman yerel bir Boolean türü _Bool(veya boolvarsa stdbool.h) vardır.
dreamlax

5

Evet, BOOL objc.h.'ye göre imzalı bir karakter için bir typedef.

Yine de bool hakkında bir fikrim yok. Bu bir C ++ işi, değil mi? Eğer 1 EVET / true ve 0 NO / false olduğu imzalı bir karakter olarak tanımlanmışsa, hangisini kullandığınızın bir önemi olmadığını hayal ediyorum.

Ancak BOOL, Objective-C'nin bir parçası olduğundan, netlik için bir BOOL kullanmak muhtemelen daha mantıklıdır (diğer Objective-C geliştiricileri, kullanımda bir bool görürlerse şaşkın olabilirler).


6
_Bool C99'da tanımlanır ve stdbool.h standart başlığında makro bool tanımlanır (_Bool'a genişler) ve true / false burada da tanımlanır.
Brian Mitchell

4

Bool ve BOOL arasındaki diğer bir fark, anahtar / değer gözlemini yaptığınızda veya - [NSObject valueForKey:] gibi yöntemleri kullandığınızda tam olarak aynı tür nesnelere dönüştürülmemesidir.

Herkesin söylediği gibi, BOOL karakterdir. Bu şekilde, bir karakter tutan bir NSNumber'a dönüştürülür. Bu nesne, 'A' veya '\ 0' gibi normal bir karakterden oluşturulan bir NSNumber'dan ayırt edilemez. Başlangıçta bir BOOL'a sahip olduğunuz bilgileri tamamen kaybettiniz.

Ancak bool, NSNumber ile aynı şekilde davranan, ancak nesnenin boole kaynağını koruyan bir CFBoolean biçimine dönüştürülür.

Bunun bir BOOL ve bool tartışmasında bir argüman olduğunu düşünmüyorum, ama bu sizi bir gün ısırabilir.

Genel olarak konuşursak, BOOL ile gitmelisiniz, çünkü bu, Cocoa / iOS API'larında (C99'dan ve yerel bool tipinden önce tasarlanmış) her yerde kullanılan türdür.


2

Kabul edilen cevap düzenlendi ve açıklaması biraz yanlış oldu. Kod örneği yenilendi, ancak aşağıdaki metin aynı kaldı. Mimari ve platforma bağlı olduğu için BOOL'un şimdilik bir karakter olduğunu varsayamazsınız. Bu nedenle, 32bit platformda (örneğin iPhone 5) kod çalıştırır ve @encode (BOOL) yazdırırsanız, "c" görürsünüz. Bir karakter türüne karşılık gelir . Eğer iPhone 5s (64 bit) kod çalıştırırsanız Ama "B" göreceksiniz. Bir bool tipine karşılık gelir .


1

Burada konvansiyona karşıyım. Typedef'i temel tiplere sevmiyorum. Bence değeri kaldıran işe yaramaz bir dolaylama.

  1. Kaynağınızdaki taban türünü gördüğümde hemen anlayacağım. Eğer bir typedef ise, gerçekten neyle uğraştığımı görmek için bakmalıyım.
  2. Başka bir derleyiciye aktarırken veya başka bir kitaplık eklerken, typedefs kümeleri çakışabilir ve hata ayıklaması zor sorunlara neden olabilir. Aslında bununla başa çıktım. Bir kütüphanede boolean int olarak tanımlandı ve mingw / gcc'de bir karakter türüne göre tanımlandı.

4
Pekala ... yapabilirsiniz standart typedef kendi dilinizde (düşünmek ait olduğunu biliyoruz beklenebilir size_t) ve her iki bool(C99) ve BOOLo kategori içine (objc) sonbahar. Kodunuz typedef değişikliği nedeniyle başarısız olduysa, typedef'i opak bir şey olarak ele almadığınız, ancak tek bir platformda uygulanmasına güvendiğiniz için suçlanacak olan kodunuzdur. (Utanacak bir şey yok, olur, ama suçlanacak typedef değil.)
DevSolar

1
"Standart" typedefler çok standart gibi görünmüyor (örneğin MS bir süredir posix standartlarını desteklemiyordu vb.). Typedefs kullanmıyorsanız, farklı derleyicilerde typedefs değiştirme veya farklı olma sorunu ortadan kalkar.
Jay

1
-1, typedefs genel olarak iki önemli amaca hizmet eder (diğerleri arasında): iyi anlambilim sağlamak ve bazı yanlış yönlendirmeler sağlamak. İdeal olarak, bir typedef'in ifade ettiği taban tipini bilmenize gerek yoktur, maalesef bu sistem mükemmel değildir ve bazen bilmeniz gerekir. Demek istediğim şu: sözleşmeyi takip etmelisiniz çünkü mükemmel olmadığını kabul etmek bile alternatiften daha iyi.
João Portela

2
@Jay: Üzgünüm, bu "yanlış yönlendirmenin" neden iyi olduğunu açıklamalıydım. Bir örnek sağlamaya çalışacağım: doğrudan int veya char kullanmak yerine typedef'd boolean kullanıyorsanız, kodunuzu kırmadan her platformda farklı bir türün (hala çalışır) kullanılmasına izin veriyorsunuz [nedenleri bu farklılık gösterir, ancak bir karakterin bellekte yanlış hizalanabileceği ve bu nedenle daha yavaş olabileceği için bir boolean için int kullanılabilir.
João Portela

2
@Jay: "İyi anlambilim" ile kastedilen BOOL varnameyerine boolean'ınızı char varnamebildirdiğinizde, bu değişken için iki geçerli değerin true/ YESveya false/ olduğu daha açıktır NO.
João Portela

1

Yukarıda belirtildiği gibi , mimariye bağlı BOOLolarak bir unsigned chartür olabilir, ancak booltiptir int. Basit bir deney, BOOL ve bool'un neden farklı davranabileceğini gösterecektir:

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

Sürpriz sizin if(objcBOOL != YES)için derleyici tarafından 1 olarak değerlendirilecektir, çünkü YESaslında karakter kodu 1'dir ve derleyicinin gözünde, karakter kodu 64 elbette karakter kodu 1'e eşit değildir, bu nedenle if ifadesi değerlendirilir YES/true/1ve aşağıdaki satır Çalıştırmak. Ancak sıfır olmayan bir booltür her zaman 1 tamsayı değerini değerlendirdiğinden, yukarıdaki sorun kodunuzu etkilemez. Eğer Objective-C BOOLtürü vs türü kullanmak istiyorsanız aşağıda bazı iyi ipuçları ANSI C bool:

  • Her zaman YESveya NOdeğerini atayın ve başka bir şey atamayın .
  • Beklenmedik sonuçlardan kaçınmak için BOOLçift ​​değil !!operatör kullanarak türleri dönüştürün .
  • YESKullanım kontrol if(!myBool) instead of if(myBool != YES)edilirken değil !operatörün kullanılması çok daha temiz ve beklenen sonucu verir.

1

Ayrıca, özellikle bitmasklerle çalışırken, imzalı karaktere döküm nedeniyle dökümdeki farklılıkların farkında olun:

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

BOOL, bool yerine imzalı bir karakterse, 0x0100 - BOOL kademesi ayarlanan biti düşürür ve sonuçta ortaya çıkan değer 0 olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.