Когда я использую 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