Оценка (NSIntegers) внутри if-statement Objective-C

Я сомневаюсь, почему эта работа правильна:

NSInteger row = indexPath.row; NSInteger preloadTrigger = self.nodes.count - 20; if (row >= preloadTrigger) { [self.loader loadNextposts]; } 

И это не так (просто пропускает if-statement):

 if (indexPath.row >= self.nodes.count - 20) { [self.loader loadNextposts]; } 

когда значение self.nodes.count - 20 отрицательно.

Однако, когда значение выражения положительное, оно отлично работает.

Очень странное поведение, поскольку я не вижу семантической разницы в двух выражениях.

Обновление: Итак, я решил проверить его:

 (lldb) po self.nodes.count - 20 18446744073709551601 (lldb) po preloadTrigger -15 

Согласно Apple Docs , свойство count является NSUInteger в NSUInteger -C.

Когда вы пишете:

  NSInteger preloadTrigger = self.nodes.count - 20; 

Фактически вы выполняете count до объекта NSInteger и можете иметь отрицательное значение, если count не превышает 20.

Но когда вы пишете:

 (indexPath.row >= self.nodes.count - 20) 

count – объект NSUInteger , и вычесть 20 из него всегда приведет к положительному числу (кстати, огромному).

Поскольку node.count – NSUInteger, а row – NSInteger. Unsigned integer – 20 никогда не является отрицательным значением, но дает огромное положительное значение, когда вы ожидаете, что оно будет отрицательным.

Я добавлю некоторые объяснения к другому, правильные ответы.

Итак, вот как это получается:

self.nodes.count имеет тип NSUInteger, который совпадает с unsigned long int в 64-битных системах или, альтернативно, unsigned int в 32-битных системах.

Литерал 20 имеет тип int .

Когда вы формируете выражение self.nodes.count - 20 , 20 «продвигается» к неподписанному целочисленному типу другого операнда ( self.nodes.count ), потому что он имеет более широкий диапазон этих двух.

Это связано с тем, что, когда оба операнда имеют типы разного размера, меньший получает повышение до большего, чтобы сделать их равными и вычислять результат в этих терминах (в аппаратном обеспечении арифметические операции между значениями разных типов на самом деле не определены – представления бит различаются).

Проблема в том, что в обмен на возможность представления более широкого диапазона положительных значений с одинаковой длиной бита беззнаковые целые числа не могут представлять отрицательные значения. Итак, когда 20 больше, чем self.nodes.count , результат «обертывается» к большому целому числу без знака.

С другой стороны, indexPath.row тоже представляет собой целое число без знака ( NSUInteger ), поэтому вы сравниваете относительно небольшое значение строки с огромным результатом операции вычитания; тест:

 if (indexPath.row >= self.nodes.count - 20) 

… всегда терпит неудачу (левая сторона меньше).

Если вы сначала передали оба результата в целое число со знаком, а затем сравнили эти целые числа:

 NSInteger row = indexPath.row; NSInteger preloadTrigger = self.nodes.count - 20; if (row >= preloadTrigger) { 

… тогда нет обертывания / недочета, и вы получите ожидаемый результат.

  • Отправить местоположение после 20-метровых различий на сервере в фоновом режиме в ios
  • UIBarButton в панели инструментов навигационного контроллера
  • Как использовать NSURLCache для кэширования содержимого, обслуживаемого NSURLProtocol
  • Делегатор UIImagePickerController не вызывается, когда sourceType является Photo Library
  • NSBundle pathForResource: возвращает nil
  • Получение предупреждения о сохранении памяти после сохранения 80 ekevents
  • Как параллельный запрос AFNetworking и ответ процесса в последовательности с реактивным какао
  • Где я могу скачать для OS X 10.10 SDK для запуска приложения Mac в Xcode 6.3?
  • iOS: отключено меню UIMenuItem
  • Лучший способ получить индексы совпадающих объектов в NSArray в iOS?
  • Использование TLS V1.1 / V 1.2 с NSURLConnection
  • Давайте будем гением компьютера.