Цель-C: BOOL против bool - PullRequest
       55

Цель-C: BOOL против bool

187 голосов
/ 12 февраля 2009

Я видел "новый тип" BOOL (YES, NO).

Я читал, что этот тип почти как символ.

Для тестирования я сделал:

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

Приятно видеть, что оба журнала отображают «1» (иногда в C ++ bool имеет тип int и его размер равен 4)

Так что мне просто интересно, были ли какие-то проблемы с типом bool или что-то в этом роде?

Могу ли я просто использовать bool (который, кажется, работает) без потери скорости?

Ответы [ 9 ]

194 голосов
/ 13 февраля 2009

Из определения в 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)

Итак, да, вы можете предположить, что BOOL - это символ. Вы можете использовать тип (C99) bool, но все платформы Apple Objective-C и большая часть кода Objective-C / Cocoa используют BOOL, поэтому вы избавите себя от головной боли, если typedef когда-либо изменится, просто используя BOOL.

33 голосов
/ 22 июня 2011

Как уже упоминалось выше, BOOL является подписанным символом. bool - тип из стандарта C99 (int).

BOOL - ДА / НЕТ. bool - правда / ложь.

См. Примеры:

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

И результат

REAL b1
НАСТОЯЩИЙ b2
НЕ РЕАЛЬНО b2

Обратите внимание, что bool! = BOOL. Результат ниже только ОДИН РАЗ - РЕАЛЬНО b2

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

Если вы хотите конвертировать bool в BOOL, используйте следующий код

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

Итак, в нашем случае:

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

И так .. что мы получаем сейчас? : -)

11 голосов
/ 30 октября 2015

На момент написания статьи это самая последняя версия 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

Это означает, что на 64-разрядных устройствах iOS и на WatchOS BOOL - это то же самое, что и bool, тогда как на всех других устройствах (OS X, 32-разрядная iOS) это signed char и даже не может переопределено флагом компилятора -funsigned-char

Это также означает, что этот пример кода будет работать по-разному на разных платформах (протестировал сам):

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

Кстати, никогда не присваивайте такие вещи, как array.count переменной BOOL, поскольку около 0,4% возможных значений будут отрицательными.

8 голосов
/ 12 февраля 2009

Тип Objective-C, который вы должны использовать: BOOL. Нет ничего похожего на родной логический тип данных, поэтому, чтобы быть уверенным, что код компилируется на всех компиляторах, используйте BOOL. (Это определено в Apple-Frameworks.

5 голосов
/ 12 февраля 2009

Да, BOOL - это typedef для подписанного символа в соответствии с objc.h.

Хотя я не знаю про bool. Это C ++, верно? Если он определен как символ со знаком, где 1 - YES / true, а 0 - NO / false, тогда я думаю, что не имеет значения, какой из них вы используете.

Поскольку BOOL является частью Objective-C, тем не менее, для ясности, вероятно, имеет смысл использовать BOOL (другие разработчики Objective-C могут быть озадачены, если увидят, что используется bool).

4 голосов
/ 08 мая 2012

Другое различие между bool и BOOL состоит в том, что они не преобразуются точно в один и тот же тип объектов, когда вы выполняете наблюдение значения ключа или когда вы используете такие методы, как - [NSObject valueForKey:].

Как все здесь сказали, BOOL - это символ. Как таковой, он преобразуется в NSNumber с символом. Этот объект неотличим от NSNumber, созданного из обычного символа, такого как «A» или «\ 0». Вы полностью потеряли информацию о том, что у вас изначально была БУЛА.

Однако bool преобразуется в CFBoolean, который ведет себя так же, как NSNumber, но сохраняет логическое происхождение объекта.

Я не думаю, что это аргумент в дебатах BOOL vs. bool, но это может укусить вас однажды.

Вообще говоря, вам следует использовать BOOL, поскольку этот тип используется везде в API-интерфейсах Cocoa / iOS (разработан до C99 и его родного типа bool).

2 голосов
/ 13 февраля 2016

Принятый ответ был отредактирован, и его объяснение стало немного неправильным. Образец кода был обновлен, но текст ниже остался прежним. Вы не можете предполагать, что BOOL является символом на данный момент, поскольку это зависит от архитектуры и платформы. Таким образом, если вы запустите свой код на 32-битной платформе (например, iPhone 5) и напечатаете @encode (BOOL), вы увидите «c». Это соответствует типу char . Но если вы запустите свой код на iPhone 5s (64 бит), вы увидите «B». Это соответствует типу bool .

1 голос
/ 12 декабря 2017

Как упоминалось выше, BOOL может иметь тип unsigned char в зависимости от вашей архитектуры, тогда как bool имеет тип int. Простой эксперимент покажет разницу, почему BOOL и bool могут вести себя по-разному:

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

К вашему удивлению if(objcBOOL != YES) будет оцениваться компилятором в 1, поскольку YES на самом деле является символьным кодом 1, а в глазах компилятора код символа 64, конечно, не равен в код символа 1 , таким образом, оператор if будет иметь значение YES/true/1, и будет выполняться следующая строка. Однако, поскольку тип bool без нуля всегда имеет целочисленное значение 1, вышеуказанная проблема не повлияет на ваш код. Ниже приведены некоторые полезные советы, если вы хотите использовать тип Objective-C BOOL против типа ANSI C bool:

  • Всегда присваивайте значение YES или NO и ничего больше.
  • Преобразование BOOL типов с помощью оператора двойной не !!, чтобы избежать неожиданных результатов.
  • При проверке YES используйте if(!myBool) instead of if(myBool != YES), гораздо удобнее использовать оператор not ! и вы получите ожидаемый результат.
1 голос
/ 05 апреля 2010

Я иду против соглашения здесь. Я не люблю typedef для базовых типов. Я думаю, что это бесполезная косвенность, которая удаляет значение.

  1. Когда я увижу базовый тип в вашем источнике, я сразу пойму это. Если это typedef, я должен посмотреть его, чтобы понять, с чем я действительно имею дело.
  2. При переносе на другой компилятор или добавлении другой библиотеки их набор typedefs может конфликтовать и вызывать проблемы, которые трудно отладить. Я только что закончил с этим. В одной библиотеке логический тип был определен как int, а в mingw / gcc он был определен как символ.
...