si estamos hablando de C y bla no está bajo su control, a continuación, sólo hacer esto:
if(blah) number += (1<<n);
no hay realmente un valor lógico en C y no tiene que ser, falso es cero y verdadera no es cero, por lo que no se puede asumir que no es cero es 1, que es lo que se necesita para su solución, ni se puede asumir que cualquier bit particular en bla se establece, por ejemplo:
number += (blah&1)<<n;
no necesariamente trabajar ya sea porque 0x2 o 0x4 o cualquier cosa que no sea cero con el bit cero claro es considerado d un verdadero. Normalmente encontrará que 0xFFF ... FFFF (menos uno, o todos) se usan como verdaderos, pero no puede confiar en los típicos.
Ahora, si usted tiene el control completo sobre el valor en bla, y mantenerlo estrictamente a un 0 para falso y 1 para la verdadera entonces se podría hacer lo que preguntabas:
number += blah<<n;
y evitar el potencial de una rama, relleno de línea de caché adicional, etc.
Volver al caso genérico, sin embargo, tomar esta solución genérica:
unsigned int fun (int blah, unsigned int n, unsigned int number)
{
if(blah) number += (1<<n);
return(number);
}
y compilación de los dos más popu lar/plataformas usadas:
testl %edi, %edi
movl %edx, %eax
je .L2
movl $1, %edx
movl %esi, %ecx
sall %cl, %edx
addl %edx, %eax
.L2:
Lo anterior usa una rama condicional.
El que se muestra a continuación utiliza la ejecución condicional, sin ramificación, sin alineación de tubería, es determinista.
cmp r0,#0
movne r3,#1
addne r2,r2,r3,asl r1
mov r0,r2
bx lr
podría haber salvado la r0 mov, instrucción r2 reorganizando los argumentos en la llamada de función, pero que es académica, te podría quemar una llamada de función en esta normalmente.
EDIT:
Como se sugiere:
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
sin duda más barato, y el código se ve bien, pero me molestaría hacer suposiciones de que el resultado de bla = 0, que es cero o todo lo que el compilador ha definido como verdadero siempre tiene el conjunto lsbit. No tiene que tener ese bit configurado para que el compilador genere código de trabajo. Tal vez las normas dictan el valor específico para verdadero. al volver a organizar los parámetros de la función, el número if (blah) + = ... también dará como resultado tres instrucciones de reloj individuales y no tendrá suposiciones.
Edit2:
En cuanto a lo que yo entiendo que es el estándar C99:
El == (igual a) y = (no iguales a) Los operadores son análogas a la relacional operadores a excepción de su menor precedencia. Cada uno de los operadores produce 1 si la relación especificada es verdadera y 0 si es falsa.
Lo que explica por qué la edición anterior funciona y por qué obtienes la movne r0, # 1 y no otro número aleatorio. El cartel hacía la pregunta con respecto a C pero también señalaba que ADA era el idioma actual, desde una perspectiva independiente del lenguaje no debe asumir "características" como la característica C anterior y usar un número if (blah) = número + (1 < < n). Pero esto se solicitó con una etiqueta C, por lo que el resultado más genérico (independiente del procesador) para C es, creo, el número + = (blah! = 0) < < n; Así que el comentario de Steven Wright tenía razón y debería obtener crédito por esto.
La suposición de los carteles también es básicamente correcta, si puede obtener bla en una forma 0 o 1, entonces usarlo en las matemáticas es más rápido en el sentido de que no hay ramificación. Conseguirlo en esa forma sin que sea más caro que una sucursal es el truco.
¿Qué pasa con la etiqueta C? –
El operador de interrelación^significa XOR en C, así que tenlo en cuenta. – chrisaycock
Ten cuidado. Como C no tiene un tipo booleano incorporado, no hay garantía de que blah sea igual a 1 o 0. Algunas funciones que devuelven verdadero o falso pueden elegir devolver algo distinto de 1 en lugar de verdadero. – Brian