#objective-c #c #cocoa
#objective-c #c #cocoa
Вопрос:
Недавно я столкнулся с очень редко воспроизводимой ошибкой. Если я приведу указатель, который не равен нулю, к BOOL по какой-то причине, я получу NO!!!11 Я знаю, что BOOL — это typedef символа со знаком. Может ли это быть проблемой?
Комментарии:
1. Для потомков, не могли бы вы включить пример того, как вы приводите к BOOL? Используя
(BOOL)var
?2. Да. Я бы ожидал, что это даст неверный результат. Но я бы также ожидал, что просто
BOOL b = var;
сработает; если бы это не сработало, мне пришлось бы исправлять много кода. 🙂
Ответ №1:
Если указатель имеет вид 0xNNNNNN00
или (в 64-разрядной версии) 0xNNNNNNNNNNNNNN00
, где N
любая шестнадцатеричная цифра, то приведение к BOOL
(an unsigned char
) оставит вас с 0
, поскольку оно усечет все ненулевые биты.
Чтобы правильно преобразовать указатель в BOOL
, используйте оператор неравенства:
BOOL isNotNull = (myPointer != NULL);
Комментарии:
1. Не могли бы вы сказать мне, «if (obj)» приводит obj к какому типу?
2. Вы можете действовать так, как если бы он приводил к
BOOL
через оператор неравенства; на практике это может быть, а может и не быть на самом деле, в зависимости от набора команд системы.if (aPointer)
всегда должно работать должным образом. 🙂
Ответ №2:
Это потому, что размер указателя составляет 32 бита, а char — всего 8 бит. Таким образом, при преобразовании из указателя в символ, он будет обрезать 24 бита. Таким образом, вероятность того, что оставшиеся 8 бит являются просто нулями, довольно высока, особенно когда адрес указателей высокий.
Что вы можете сделать, так это следующее:
BOOL myBool = (myPointer != NULL); // This will evaluate if the pointer is true (>0) or false (NULL)
Комментарии:
1. @Jonathan: Извините, это больше не повторится. Обещано: P
Ответ №3:
BOOL
это не тот тип, который следует использовать, именно по этой причине. На самом деле, я могу придумать мало пользы для переменной логического типа (в отличие от простого использования исходного значения, указателя или чего-то еще, на чем она основана), за исключением случая гигантских битовых массивов, где вам понадобится специальный код для адресации битов. Если вам действительно нужен логический тип, используйте C99 _Bool
(или bool
в stdbool.h
), который имеет правильную семантику преобразования, а не уменьшение по модулю 256.