Возможно, вы пытаетесь проверить, даст ли добавление x и y действительный результат как uint32_t. Проблема, как уже говорилось в комментариях, заключается в том, что если число слишком «большое», преобразование из uint64_t в uint32_t не определено.
В настоящее время ни C, ни C ++ не предполагают, что числа представлены как дополнение к двум иэтот вид проверки сложен. Это изменится, так как следующий стандарт C ++ обеспечит использование дополнения two к целым числам со знаком (и, вероятно, будет следовать стандарт C).
Но это не даст смыслав неправильное преобразование, и ваш код по-прежнему будет недействительным.
Некоторые тесты могут быть выполнены, если мы предположим, что числа закодированы в дополнение к двум (и это уже поведение на большинстве компьютеров).
Можно использовать несколько решений. Вот тот, который в основном опирается на побитовые операторы.
Схема метода:
числа сдвига влево, чтобы разделить их на два (предполагается, что сдвиги влево на знаковых являются арифметическими, что верно для большинства компьютеров, но не требуется в настоящее время стандартом)
добавить их. Это вычислит x / 2 + y / 2 и будет равно (x + y) / 2 , за исключением , если оба LSB равны x и y - это единицы, в этом случае существует перенос, сгенерированный с весом 2 ^ 1 в x + y .
Мы проверяем существование этого переноса с помощью и с младшим битом x и y , и мы добавляем его к сумме.
результат предыдущеговычисление (x + y) / 2 всегда допустимо для 32 бит. Мы проверяем, действительно ли это на 31 бит. Если это правда, x + y будет действительным для 32 битов.
Проверка этой действительности выполняется путем сравнения битов 31 и 30. Если они равны, результат может быть преобразован в 31Бит безопасно. В противном случае преобразование вызовет изменение знака.
int is_add32_valid(uint32_t x, uint32_t y) {
uint32_t z = (x>>1) + (y>>1) + (x & y & 0x1) ;
return !( (z ^ (z <<1)) & (1 << 31) ) ;
}