Пожалуйста, объясните, почему первый фрагмент кода не дает -1.
string s = "abc";
int amount = -1;
cout << "amount to shift before modulus: " << amount<<endl;
amount %= s.size();
cout << "mod " <<s.size()<<endl;
cout << "amount to shift after modulus: " << amount<<endl;
Вывод:
величина сдвига перед модулем: -1
мод 3
количество сдвига после модуля: 0
string s = "abc";
int sSize = s.size();
int amount = -1;
cout << "amount to shift before modulus: " << amount<<endl;
amount %= sSize;
cout << "mod " <<sSize<<endl;
cout << "amount to shift after modulus: " << amount<<endl;
Вывод:
величина сдвига перед модулем: -1
мод 3
количество сдвига после модуля: -1
Я выполнял задачу по кодированию, когда столкнулся с таким поведением, и я не понимаю, что происходит. Этого не происходит, если сумма является положительным числом, например 1.
1 ответ
Если вы выполняете арифметические действия (включая арифметическое сравнение) между целым числом со знаком и целым числом без знака, а тип целого числа без знака имеет ширину не менее целого числа со знаком, то целое число со знаком преобразуется в целое число без знака . (Это результат так называемых «обычных арифметических преобразований». )
Это почти всегда дает неожиданные результаты, если только арифметическая операция не является сложением или вычитанием. Во многих случаях хороший компилятор предупредит вас о выполнении арифметики со смешанными знаками, если вы запросите предупреждения. (Настоятельно рекомендуется!) Это лишь один относительно необычный вариант.
В первом случае s.size()
имеет тип size_t
, который является беззнаковым типом, вероятно, 64-битным; следовательно, он шире, чем int
. Итак, чтобы вычислить amount % s.size()
, компилятор сначала преобразует amount
в беззнаковый size_t
, что приведет к 2 64 -1. Оказывается, это число делится на 3, поэтому операция по модулю возвращает 0.
Во втором случае вы принудительно преобразовываете s.size()
в целое число со знаком. Поскольку значение определенно находится в пределах int
, преобразование четко определено. Последующая операция по модулю выполняется для подписанных int
s и дает ожидаемый результат, если вы ожидаете, что подписанный модуль будет работать так же, как в C ++. (См. Почему C ++ выводит отрицательные числа при использовании по модулю? a> для получения дополнительной информации.)
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .