Подтвердить что ты не робот

Objective-C: BOOL против bool

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

Я читал, что этот тип почти похож на char.

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

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

Хорошо видеть, что оба журнала отображают "1" (иногда в С++ bool - это int, а его размер - 4)

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

BOOL - ДА/НЕТ. bool - true/false.

См. примеры:

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
REAL b2
NOT REAL b2

Обратите внимание, что bool!= BOOL. Результат ниже - ONCE AGAIN - REAL 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");

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

Ответ 3

На момент написания это самая последняя версия 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% возможных значений будут отрицательными.

Ответ 4

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

Ответ 5

Yup, BOOL является typedef для подписанного char в соответствии с objc.h.

Однако я не знаю о bool. Это С++, да? Если он определен как подписанный char, где 1 - ДА/Истина, а 0 - NO/false, то я полагаю, что не имеет значения, какой из них вы используете.

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

Ответ 6

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

Как сказано выше, BOOL - char. Таким образом, он преобразуется в NSNumber с char. Этот объект неотличим от NSNumber, созданного из обычного char, такого как "A" или "\ 0". Вы полностью потеряли информацию о том, что изначально у вас был BOOL.

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

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

Как упоминалось выше, 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, используя двойной оператор not !!, чтобы избежать неожиданных результатов.
  • При проверке YES используйте if(!myBool) instead of if(myBool != YES), гораздо удобнее использовать оператор not ! и вы получите ожидаемый результат.

Ответ 10

Также следует помнить о различиях в приведении типов, особенно при работе с битовыми масками, из-за преобразования в подписанные символы:

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, приведение 0x0100 к BOOL просто сбрасывает установленный бит, и полученное значение равно 0.