Это происходит из-за обычных арифметических преобразований .
Когда операнды оператора включают в себя как целое число со знаком, так и целое число без знака, а тип без знака по меньшей мере такой же большой, кактип со знаком, значение со знаком преобразуется в значение без знака.Когда значение со знаком является отрицательным, оно преобразуется в большое положительное значение.
Правила целочисленных преобразований изложены в разделе 6.3.1.8p1 стандарта C :
Если оба операнда имеют одинаковый тип, дальнейшее преобразование не требуется.
В противном случае, если оба операнда имеют целочисленные типы со знаком или у обоих целочисленные типы без знака, операнд с типом меньшегоранг целочисленного преобразования преобразуется в тип операнда с большим рангом.
В противном случае, если операнд с целым типом без знака имеет ранг, больший или равный рангу типа другого операнда, тогда операндс целым типом со знаком преобразуется в тип операнда с целым типом без знака.
В противном случае, если тип операнда с целочисленным типом со знаком может представлять все значения типа операнда с целым числом без знакатип, то операнд с целым типом без знака преобразуется в тип operand со целым типом со знаком.
В противном случае оба операнда преобразуются в целочисленный тип без знака
, соответствующий типу операнда со целым типом со знаком
В этом выражении:
(d <= TOTAL_ELEMENTS - 2)
Что расширяется до:
(d <= (sizeof(array) / sizeof(array[0])) - 2)
Оператор sizeof
оценивает значение типа size_t
, которое не подписано.Таким образом, типы операндов выглядят так:
(int <= ((size_t / size_t) - int)
Оба операнда оператора /
имеют тип size_t
, поэтому результат этой операции имеет тип size_t
.Затем правый операнд -
преобразуется в тип size_t
.Поскольку значение 2 соответствует этому типу, значение не изменяется.
Теперь у нас есть оператор <=
с int
для одного размера и size_t
для другого.Левый операнд преобразуется из int
в size_t
, однако значение -1 не подходит для этого типа, поэтому оно преобразуется.Преобразованное значение на самом деле является наибольшим возможным значением для size_t
, которое, следовательно, больше, чем значение на правой стороне, что делает результат <=
ложным.
Чтобы это исправить, вам нужноприведите значение без знака справа к знаку, чтобы предотвратить преобразование левой стороны:
if (d <= (int)(TOTAL_ELEMENTS - 2))