Когда я использую BOOL для 32-битного, я получаю:
BOOL b1=8960; //b1 == NO
bool b2=8960; //b2 == true
Но для 64-битного я получаю:
BOOL b1=8960; //b1 == YES
bool b2=8960; //b2 == true
Что изменилось в BOOL с 32-битного до 64-битного?
Когда я использую BOOL для 32-битного, я получаю:
BOOL b1=8960; //b1 == NO
bool b2=8960; //b2 == true
Но для 64-битного я получаю:
BOOL b1=8960; //b1 == YES
bool b2=8960; //b2 == true
Что изменилось в BOOL с 32-битного до 64-битного?
@TimBodeit прав, но это не объясняет, почему...
BOOL b1=8960; //b1 == NO
... оценивается до NO на 32-разрядной iOS и почему он оценивает YES в 64-битном iOS. Пусть начнется с того же начала.
Определение OBJC BOOL
#if (TARGET_OS_IPHONE && __LP64__) || (__ARM_ARCH_7K__ >= 2)
#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 или ARMv7k (часы) он определяется как bool, а остальное как signed char.
ObjC BOOL YES и NO
Прочтите Objective-C Литералы, где вы можете найти:
Раньше тип
boolбыл просто typedef дляsigned char, иYESиNOбыли макросы, которые расширяются до(BOOL)1и(BOOL)0соответственно. Для поддержки выражений@YESи@NOэти макросы теперь определяется с использованием новых языковых ключевых слов в<objc/objc.h>:
#if __has_feature(objc_bool)
#define YES __objc_yes
#define NO __objc_no
#else
#define YES ((BOOL)1)
#define NO ((BOOL)0)
#endif
Компилятор неявно преобразует
__objc_yesи__objc_noв(BOOL)1и(BOOL)0. Ключевые слова используются для устранения неоднозначности BOOL и целого числа литералы.
определение bool
bool - это макрос, определенный в stdbool.h, и он расширяется до _Bool, который является булевым типом, введенным в C99. Он может хранить два значения, 0 или 1. Ничего больше. Точнее, stdbool.h определяет четыре макроса для использования:
/* Don't define bool, true, and false in C++, except as a GNU extension. */
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Define _Bool, bool, false, true as a GNU extension. */
#define _Bool bool
#define bool bool
#define false false
#define true true
#endif
#define __bool_true_false_are_defined 1
_Bool
_Bool был введен в C99 и он может содержать значения 0 или 1. Что важно:
Когда значение понижается до уровня
_Bool, результат равен0, если значение равно0и1в противном случае.
Теперь мы знаем, откуда этот беспорядок, и мы можем лучше понять, что происходит.
64-бит iOS || ARMv7k
bool → bool → _Bool (значения 0 или 1)
Demoting 8960 to _Bool дает 1, потому что значение не равно 0. См. Раздел (_Bool).
32-разрядная iOS
bool → signed char (значения -128 до 127).
Если вы собираетесь хранить значения int (-128 до 127) как signed char, значение не изменяется на C99 6.3.1.3. В противном случае это реализация определена (C99 цитата):
В противном случае новый тип подписан и значение не может быть представлено в этом; либо результат определяется реализацией или сигнал, определяемый реализацией.
Это означает, что clang может решить. Чтобы сделать его коротким, с настройками по умолчанию, clang обертывает его вокруг (int → signed char):
-129 становится 127,-130 становится 126,-131 становится 125,И в противоположном направлении:
128 становится -128,129 становится -127,130 становится -126,Но поскольку signed char может хранить значения в диапазоне от -128 до 127, он также может хранить 0. Например 256 (int) становится 0 (signed char). И когда ваше значение 8960 обернуто вокруг...
8960 становится 0,8961 становится 1,8959 становится -1,... он становится 0 при сохранении в signed char (8960 является кратным 256, 8960 % 256 == 0), поэтому он NO. То же самое относится к 256, 512,... кратным 256.
Я настоятельно рекомендую использовать YES, NO с bool и не полагаться на причудливые функции C, такие как int как условие в if и т.д. По этой причине Swift имеет bool, true и false, и вы не можете использовать значения int в условиях, когда ожидается bool. Просто, чтобы избежать этого беспорядка...
Для 32-битного BOOL есть signed char, тогда как под 64-бит это bool.
Определение BOOL из 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