Sí, es posible. Por ejemplo, gcc
puede usar __builtin_unreachable
para decirle al compilador acerca de condiciones imposibles, así:
if (value < 0 || value > 36) __builtin_unreachable();
Podemos envolver la condición anterior en una macro:
#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
Y úsalo así:
assume(x >= 0 && x <= 10);
Como puede ver , gcc
realiza optimizaciones basadas en esta información:
#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
int func(int x){
assume(x >=0 && x <= 10);
if (x > 11){
return 2;
}
else{
return 17;
}
}
Produce:
func(int):
mov eax, 17
ret
Sin embargo, una desventaja es que si su código alguna vez rompe tales suposiciones, obtendrá un comportamiento indefinido .
No le avisa cuando esto sucede, incluso en las versiones de depuración. Para depurar / probar / atrapar errores con suposiciones más fácilmente, puede usar una macro híbrida asumir / afirmar (créditos a @David Z), como esta:
#if defined(NDEBUG)
#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#else
#include <cassert>
#define assume(cond) assert(cond)
#endif
En las compilaciones de depuración ( NDEBUG
sin definir), funciona como un assert
mensaje de error de impresión ordinario y un abort
programa 'ing', y en las compilaciones de lanzamiento utiliza una suposición, produciendo código optimizado.
Sin embargo, tenga en cuenta que no es un sustituto de la versión regular assert
: cond
permanece en las versiones de lanzamiento, por lo que no debe hacer algo así assume(VeryExpensiveComputation())
.
unsigned
tipos, ya que es más fácil para el compilador razonar con ellos.var value: 0..36;
.int
y esunsigned int
necesario extender el signo o cero de 32 a 64 bits, también, en la mayoría de los sistemas con punteros de 64 bits. Tenga en cuenta que en x86-64, las operaciones en registros de 32 bits se extienden de cero a 64 bits de forma gratuita (no se extiende la señal, pero el desbordamiento firmado es un comportamiento indefinido, por lo que el compilador solo puede usar matemática firmada de 64 bits si lo desea). Por lo tanto, solo verá instrucciones adicionales para argumentos de función de 32 bits de extensión cero, no resultados de cálculo. Lo haría para tipos sin signo más estrechos.