Вопрос по iphone, compare, objective-c, boolean – В Objective-C, безопасный и хороший способ сравнить 2 значения BOOL?

9

Я хочу сравнить 2 значения BOOL в target-c.

Я обнаружил, что (3) - (6) из следующего кода работает.
(1) - (2) не работает, потому что BOOL простоsigned char.

(3) работает и очень читабелен, но я думаю,bool не является целью-c.
С помощьюbool в коде цель-с это хорошо?

Какой безопасный и хороший способ сравнить 2 значения BOOL в target-c?
Есть ли другие лучшие способы сравнения?

BOOL b = YES;
BOOL c = 2;

NSLog(@"(1) %d", b == c); // not work
NSLog(@"(2) %d", (BOOL)b == (BOOL)c); // not work
NSLog(@"(3) %d", (bool)b == (bool)c);
NSLog(@"(4) %d", !b == !c);
NSLog(@"(5) %d", !!b == !!c);
NSLog(@"(6) %d", (b != 0) == (c != 0));

Результаты:

(1) 0
(2) 0
(3) 1
(4) 1
(5) 1
(6) 1
4-й метод выглядит хорошо для меня. Он короткий и безопасно конвертирует значение в 0 или 1. nhahtdh
@NikolaiRuhe Конечно, однако, задавая вопрос о безопасном использованииBOOL а затем присваивая2не действителен. trojanfoe
2 не является действительнымBOOL значение; толькоYES а такжеNO являются. То, что вы делаете, неверно. trojanfoe
@trojanfoe: Дело в том, что Obj-C с радостью примет присвоение номера BOOL, и вы даже можете выполнять побитовую работу с ним. nhahtdh
Я согласен с trojanfoe, а также думаю, что XCode должен генерировать предупреждение в случае таких назначений. Неправильные назначения BOOL являются источником ужасных ошибок. Oleg Trakhman

Ваш Ответ

6   ответов
1

BOOLотвечая на вопрос, что вы подразумеваете под "2"

в вашем контексте 2 = ДА

Int number = 2;
BOOL c = (number == 2); //2 is YES

это & gt; 0 = ДА

Int number = 2;
BOOL c = (number > 0); //2 is YES

Это зависит только от того, что ИСТИННО, а что Неверно в вашем приложении

Этот вид преобразования не требуется, если вы используете BOOL правильно. Если вам нужно подумать об этом, то вы делаете что-то в корне неправильно. Выражение (B & amp; C) вернет YES, даже если c равно 2, а b равно 1. Можно основывать весь ваш код на выражениях такого типа, и это правильный путь в булевой алгебре. (именно поэтому он называется BOOL / bool / Boolean). См. мой ответ для ссылок.
Благодарю. Я всегда пытаюсь преобразовать в действительный BOOL при назначении после того, как узнал, что кратные 256 неявно преобразуются в 0 (НЕТ). Но возможно, что метод, созданный другим человеком, возвращает значение BOOL, отличное от 0/1. И я не конвертирую возвращенное значение BOOL в действительное значение типа BOOLb = !![obj methodWhchReturnsBOOL]; Так,c = 2 может случиться. js_
-1

ваш код будет поврежден. Что бы вы ни получили после этого, это то, что вы заслуживаете.

Поэтому единственный разумный способ сравнить две BOOL a и b

if (a == b) ...
if (a != b) ...
Я бы сказал, что единственный разумный путьif(a && b) а такжеif (!a && b), поскольку это операторы в мертвых будут настоящие логические операции, в то время как== а также!= являются числовыми операторами.
1

objc.h:

typedef signed char     BOOL; 
....

#define YES             (BOOL)1
#define NO              (BOOL)0

Судя по всему, BOOLsigned char, так что это правда, что вы можете назначить номер переменнойBOOL тип, который испортит сравнение (так как сравнение - целочисленное сравнение).

Я думаю, что ваш метод (4), использующий отрицание для преобразования произвольного интегрального значения в 0 или 1, является хорошим коротким способом безопасного сравнения логического значения 2 BOOL.

5

bool в Objective-C как части стандарта C99 (& # xA7; 7.16). По моему мнению, это также лучший способ обеспечить безопасное сравнение булевых типов.

Единственная причина не использоватьbool везде этоBOOL вездесущ в Objective-C и структурах.

@js_ Это всегда работает. Прямое назначение также должно быть безопасным с современными компиляторами без ошибок.
@JeremyP, так почему ты это делаешь?foo = bar ? true : false; или жеbar = foo ? YES : NO;? Компилятор XCode содержит ошибки? js_
я используюbool везде, кроме тех случаев, когда API-интерфейс Cocoa требуетBOOL, Безопасное преобразование из одного в другое было бы (foo - это bool, а bar - это BOOL):foo = bar ? true : false; или жеbar = foo ? YES : NO;
Назначениеtrue или жеfalse кBOOL является действительным и безопасным. Стандарт говорит, что они расширяются до целочисленных констант0 или же1 (также в & # xA7; 7.16).
Благодарю. я думал, что Bool был C ++. @ JeremyP, почемуfoo = bar; bar = foo; не безопасны? js_
9

рации XOR.

Попытка сравнить два логических значения напрямую - это неправильное использование основ булевой алгебры: http://en.wikipedia.org/wiki/Boolean_algebra_(logic)

Когда вы делаете

BOOL a = (b == c);

тогда это значение может вернуть false, даже если b и c верны. Однако выражение b & amp; c всегда будет возвращать YES, если b и c истинны, то есть больше 0, и NO в противном случае.

Вместо этого это то, что вы на самом деле пытаетесь сделать:

BOOL xor = b && !c || !b && c;
BOOL equal = !xor;

эквивалентно

BOOL equal = !(b && !c || !b && c);

или же

BOOL equal = (b && c) || (!b && !c)

Если вам нужно потратить время, чтобы убедиться, что ваши значения BOOL нормализованы (т.е. установлены в 1 или 0), то вы делаете что-то не так.

спасибо Джейк! я думаю, что вы и @Sulthan правы. это красиво, но это дольше и менее читабельно / доступно для записи, чем !! или (бул). почему у c нет логического оператора xor? js_
удобочитаемость может быть улучшена из имен переменных. Если вы, например, хотите проверить, голоден ли человек, но не устал или не устал, но не голоден, и у вас есть два одинаковых именива, тогда выражение (голодный и усталый) || (! голодный и усталый) имеет больше смысла, чем выражение (голодный! = усталый). (Как голодный может быть равен усталому, и что бы это значило?)
Четвертое выражение в вопросе OP фактически решает проблему быстро и чисто. Он просто нормализует число до 0 или 1, затем== будет вести себя как XNOR (НЕ XOR). Другие выражения (3 и 5, 6) также верны.
С программной точки зрения это безопасно и может считаться «чистым» некоторые, но я придерживаюсь мнения, что логическое выражение должно быть автономным выражением, которое будет разбито на использование & amp; & amp; только и имеет возвращаемое значение true или false. Сравнение двух булевых выражений друг с другом, нормализованных или нет, не является регулярной булевой алгеброй. ДА: if (true) if (false) if (bool1 & amp; bool2) if (bool1 & amp;! Bool2 || int1 == int2) if (int1 == int2) и т. Д. NO: if (bool1 == bool2) if (bool1 == true) if (! Bool1 == bool2) и так далее. Все они программно правильны, но последние не очень хороши для меня.
4

я хотел бы отметить, что сравнение булев на равенствоnot очень распространенная операция.BOOL не является типом, это просто макрос, который скрывает тот факт, что логические значения являются только целыми числами. Для каждой логической операции вы должны использовать программные структуры и операторы, которые могут правильно обрабатывать целые числа как логические:

например: if (condition1 == NO) {} должно бытьif (!condition1) {}

if (condition1 == condition2) {}
 может быть
if ((condition1 && condition2) || (!condition1 && !condition2)) {}
или лучше
BOOL newCondition = (condition1 && condition2) || (!condition1 && !condition2); if (newCondition) {}

Кратчайший способ написания условия не должен быть наилучшим.

Я не думаю, что сравнение булевых значений редко. Одним из распространенных случаев является установщик свойства BOOL с ярлыком быстрого возврата: - (void) setAnimate: (BOOL) animate {if (_animate == animate) return; // еще сделать все, что нужно для настройки или снятия анимации}
Также ради правильности:BOOL это не макрос, а определение типа.
Спасибоtypedef нота.old value check это что-то действительно особенное. Обычно вы вообще не заботитесь о типе собственности и даже не должны знать, что это BOOL.
Также смstackoverflow.com/questions/12131879/…

Похожие вопросы