Стандарты языка С предписывают компиляторам пользовать «быстрое» сравнение, вместо корректного.
То есть в следующем коде согласно всех стандартов языка С переменная res должна получить значение
0 а не 1, что крайне непрактично.
unsigned int a = 1;
int b = -1;
int res = (b < a);
Недавно я узнал что существует заметно больше способов корректного сравнения чем я изначально предполагал. Поэтому мне интересен чужой опыт.
Естественно речь о ситуациях где отказаться ни от знаковых, ни от беззнаковых никак нельзя.
Мой основной способ решения этой проблемы через расширение разрядности, так как я в первую очередь имею дело с unsigned char, но смесь size_t c ssize_t или что-то подобное также нередко доставляет неудобства.
Опишите кто и как выкручивается в сложившейся ситуации.
[UPDATE] ассемблерные листинги к классическим алгоритмам сравнения
For example x86 gcc 7.1 will for C++ source:
bool compare(int x, unsigned int y) {
    return (x < y); // "wrong" (will emit warning)
}
bool compare2(int x, unsigned int y) {
    return (x < 0 || static_cast<unsigned int>(x) < y);
}
bool compare3(int x, unsigned int y) {
    return static_cast<long long>(x) < static_cast<long long>(y);
}
Produce this assembly (godbolt live demo):
compare(int, unsigned int):
        cmp     edi, esi
        setb    al
        ret
compare2(int, unsigned int):
        mov     edx, edi
        shr     edx, 31
        cmp     edi, esi
        setb    al
        or      eax, edx
        ret
compare3(int, unsigned int):
        movsx   rdi, edi
        mov     esi, esi
        cmp     rdi, rsi
        setl    al
        ret
Взято вот здесь:







