Какой метод приращения лучше в C ++? - PullRequest
1 голос
/ 31 октября 2009

Я видел, как кто-то использовал этот метод для увеличения переменной:

r = (r + 1) & 0xf;

Является ли этот метод лучше / быстрее, чем просто использование:

r++;

Зачем кому-то использовать побитовое и с 0xf, если оно просто дублирует?

Ответы [ 8 ]

14 голосов
/ 31 октября 2009

Это не одно и то же. Первый увеличивает r, затем выполняет операцию по модулю, фактически делая то же самое, что и:

r = (r + 1) % 16;
11 голосов
/ 31 октября 2009

Выражение:

r = (r + 1) & 0xf;

Это на самом деле эквивалентно этому (при условии, что r гарантированно будет неотрицательным):

r = (r + 1) % 16;

Из-за этого невозможно сравнить ни одно из приведенных выше утверждений с r++. Неважно, что "быстрее" или "лучше", потому что они не делают то же самое в первую очередь.

4 голосов
/ 31 октября 2009

Как уже заявляли другие, два отправленных вами фрагмента кода не эквивалентны. Обновляя вопрос на основе этой информации, вопрос становится следующим:

r = (r + 1) & 0xf; лучше, чем r = (r + 1) % 16;?

Хотя может возникнуть ситуация, в которой прежнее обозначение более применимо, я бы сказал, что в целом нет , это не . Оператор по модулю значительно упрощает происходящее, и я думаю, что большинство компиляторов выполнят эту оптимизацию за вас. Не без необходимости жертвуйте читабельностью ради скорости. (Конечно, если вы хотите быть уверенным в любой возможной разнице в скорости, просто скомпилируйте оба фрагмента в ассемблер, например, с gcc -S, и сравните вывод.)

Edit: nobar * Замечание 1027 * ниже показывает, что вещи обычно не так просты, как кажутся. В отличие от &, % является арифметическим оператором, и он как таковой связан с некоторыми дополнительными правилами (например, для обеспечения правильной обработки отрицательных аргументов). Два приведенных выше утверждения эквивалентны только для неотрицательных значений или r. Чтобы компилятор мог сделать такое предположение о r, лучше всего объявить его unsigned.

3 голосов
/ 31 октября 2009

Эти строки не эквивалентны. Первый из них вернется к нулю, если перед вызовом r 15.

2 голосов
/ 31 октября 2009

r++ никогда не следует использовать для увеличения, если только вам не нужно предварительно увеличенное значение в качестве значения r. Большинство компиляторов оптимизируют его до ++ r, если функция постинкремента не нужна, но лучше не полагаться на нее. Но вы, вероятно, хотели спросить о сравнении между ++r и (r + 1) & 0xf;, тогда я бы сказал, что любое незначительное улучшение, которое может иметь последний конкретный компилятор или аппаратное обеспечение, незначительно по сравнению с большей сложностью в понимании и поддержании кода. .

В общем, избегайте попыток быть слишком умным в оптимизации, которая может не относиться к другой архитектуре.

1 голос
/ 31 октября 2009

Сравнение
r=(r+1) & 0xf;
и
++r;<br> r %= 0x10;
При любом виде оптимизации компилятора, когда r является целым числом, они должны быть одинаковыми.

1 голос
/ 31 октября 2009

Нет двух эквивалентов в приведенных вами примерах кода.
1) Это быстрый способ ограничения значения от 0 до 15 и выполнения обтекания до нуля, если значение превышает 15.
2) Просто увеличивает значение без верхнего предела (кроме встроенного предела, налагаемого размером типа, для которого объявляется r, т. Е. Он будет переноситься> 255, если r был объявлен как unsigned char и т. Д.)

1) эквивалентно этому

if (r + 1 > 15 )
{
   r = 0;
}

Таким образом, он может быть более оптимальным на некоторых типах оборудования, поскольку устраняет необходимость в ветке и т. Д.

0 голосов
/ 31 октября 2009

Возможно, вам следует спросить себя, какой метод clear и прост для понимания для программиста, поддерживающего ваш код ... C и C ++ дают много синтаксиса, чтобы сказать то же самое а компиляторы умнее программистов в большинстве ситуаций, поэтому ответственность за обеспечение легкого понимания кода.

...