если мы говорим о C и мля не в вашей власти, то просто сделайте это:
if(blah) number += (1<<n);
На самом деле в C нет логического значения, и оно не должно быть, false равно нулю, а true не равно нулю, поэтому вы не можете предполагать, что не ноль равно 1, что вам нужно для вашего решения, и вы не можете предполагать, что какой-либо конкретный установлен бит в blah, например:
number += (blah&1)<<n;
Не обязательно будет работать, потому что 0x2 или 0x4 или что-либо ненулевое с очищенным нулевым битом считается истинным. Обычно вы обнаружите, что 0xFFF...FFFF (минус один или все единицы) используются как истинные, но вы не можете полагаться на типичный.
Теперь, если вы полностью контролируете значение в blah и держите его строго равным 0 для false и 1 для true, тогда вы можете сделать то, о чем спрашивали:
number += blah<<n;
И избегайте возможности ветки, заполнения дополнительной строки кэша и т. д.
Однако вернемся к общему случаю, взяв это общее решение:
unsigned int fun ( int blah, unsigned int n, unsigned int number )
{
if(blah) number += (1<<n);
return(number);
}
И компиляция для двух самых популярных/используемых платформ:
testl %edi, %edi
movl %edx, %eax
je .L2
movl $1, %edx
movl %esi, %ecx
sall %cl, %edx
addl %edx, %eax
.L2:
В приведенном выше примере используется условная ветвь.
Приведенный ниже использует условное выполнение, без ветвления, без сброса конвейера, является детерминированным.
cmp r0,#0
movne r3,#1
addne r2,r2,r3,asl r1
mov r0,r2
bx lr
Можно было бы сохранить инструкцию mov r0,r2, переставив аргументы в вызове функции, но это академично, вы бы не записали вызов функции на этом обычно.
РЕДАКТИРОВАТЬ:
Как было предложено:
unsigned int fun ( int blah, unsigned int n, unsigned int number )
{
number += ((blah!=0)&1)<<n;
return(number);
}
subs r0, r0, #0
movne r0, #1
add r0, r2, r0, asl r1
bx lr
Конечно, дешевле, и код выглядит хорошо, но я бы не стал делать предположений, что результат blah!=0, который равен нулю или тому, что компилятор определил как true, всегда имеет установленный lsbit. Компилятору не обязательно устанавливать этот бит для генерации рабочего кода. Возможно, стандарты диктуют конкретное значение true. путем перестановки параметров функции число if(blah) +=... также приведет к трем одиночным тактовым инструкциям и не будет иметь предположений.
РЕДАКТИРОВАТЬ2:
Глядя на то, что я понимаю под стандартом C99:
Операторы == (равно) и != (не равно) аналогичны операторам отношения, за исключением их более низкого приоритета. Каждый из операторов возвращает 1, если указанное отношение истинно, и 0, если оно ложно.
Это объясняет, почему приведенное выше редактирование работает и почему вы получаете movne r0,#1, а не какое-то другое случайное число.
Плакат задавал вопрос относительно C, но также отметил, что ADA является текущим языком, с независимой от языка точки зрения вы не должны предполагать «функции», такие как функция C выше, и использовать if (бла) число = число + (1 ‹‹н). Но это было задано с помощью тега C, поэтому в целом (независимо от процессора) самый быстрый результат для C, я думаю, это number += (blah!=0)‹‹n; Так что комментарий Стивена Райта был правильным, и он должен получить за это признание.
Предположение плаката также в основном правильное, если вы можете получить бла в форме 0 или 1, то использование его в математике будет быстрее в том смысле, что нет ответвления. Хитрость заключается в том, чтобы получить его в этой форме, не будучи дороже, чем ветка.
27.10.2010
number += ((blah!=0)&1)<<n;
? 27.10.2010