Я столкнулся с ошибкой в написанном мною коде на языке Си, и хотя ее было относительно легко исправить, я хочу лучше понять проблему, лежащую в ее основе. По сути, дело в том, что у меня было два беззнаковых целых числа (uint32_t, на самом деле), которые при применении операции модуляции давали беззнаковый эквивалент отрицательного числа, числа, которое было обернуто и поэтому было "большим". Вот пример программы для демонстрации:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char* argv[]) {
uint32_t foo = -1;
uint32_t u = 2048;
uint64_t ul = 2048;
fprintf(stderr, "%d\n", foo);
fprintf(stderr, "%u\n", foo);
fprintf(stderr, "%lu\n", ((foo * 2600000000) % u));
fprintf(stderr, "%ld\n", ((foo * 2600000000) % u));
fprintf(stderr, "%lu\n", ((foo * 2600000000) % ul));
fprintf(stderr, "%lu\n", foo % ul);
return 0;
}
на моей машине x86_64 это дает следующий результат:
-1
4294967295
18446744073709551104
-512
1536
2047
1536 - это число, которое я ожидал, но (uint32_t)(-512) - это число, которое я получил, что, как вы можете себе представить, немного сбило ситуацию.
Итак, мой вопрос заключается в следующем: почему операция по модулю между двумя беззнаковыми числами в данном случае дает число, которое больше делителя (т.е. отрицательное число)? Есть ли причина, по которой такое поведение предпочтительно?