Результатом отрицательного % 2
является отрицательный остаток с делением, округленным до 0 в C. & 1
работает только для положительных чисел.
Таким образом, компилятор генерирует код, который добавляет числа знаковых битов - по существу, увеличивая отрицательные числа на единицу, так что -1
имеет 0
в последнем бите, затем -2
имеет 1
в последнембит, -3
снова имеет 0
... затем мы маскируем все, кроме последнего бита, и вычитаем знаковый бит из результата , например:
movl %edi, %edx
shrl $31, %edx
leal (%rdi,%rdx), %eax
andl $1, %eax
subl %edx, %eax
Возможно, это немного более эффективно, чем инструкция idiv
.На Core i7, например, IDIV с r32 будет иметь задержку 17-28 и пропускную способность 7-12, где все остальные в сгенерированном коде имеют их ~ 1 каждый