Приведение указателя, который не равен нулю, к BOOL возвращает NO

#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.