Una diferencia fundamental entre C y Java es que si se evitan ciertas características de Java fácilmente identificables (por ejemplo, aquellas en el Unsafe
espacio de nombres), cada acción posible que se pueda intentar, incluidas las "erróneas", tendrá un rango limitado de resultados posibles . Si bien esto limita lo que se puede hacer en Java, al menos sin usar el Unsafe
espacio de nombres, también permite limitar el daño que puede causar un programa erróneo o, lo que es más importante, un programa que procese correctamente archivos válidos pero no está especialmente protegido contra archivos erróneos.
Tradicionalmente, los compiladores de C procesaban muchas acciones de forma estándar en casos "normales", mientras que procesaban muchos casos de esquina "de una manera característica del entorno". Si uno usara una CPU que se cortocircuitaría y se incendiaría si ocurriera un desbordamiento numérico y quisiera evitar que la CPU se incendie, necesitaría escribir un código para evitar el desbordamiento numérico. Sin embargo, si uno usara una CPU que truncaría perfectamente los valores de manera complementaria, no tendría que evitar desbordamientos en los casos en que dicho truncamiento resultaría en un comportamiento aceptable.
Modern C lleva las cosas un paso más allá: incluso si uno apunta a una plataforma que naturalmente definiría un comportamiento para algo como el desbordamiento numérico donde el Estándar no impondría requisitos, el desbordamiento en una parte de un programa puede afectar el comportamiento de otras partes del programa de manera arbitraria no vinculada por las leyes del tiempo y la causalidad. Por ejemplo, considere algo como:
uint32_t test(uint16_t x)
{
if (x < 50000) foo(x);
return x*x; // Note x will promote to "int" if that type is >16 bits.
}
Un compilador de C "moderno" dado algo como lo anterior podría concluir que, dado que el cálculo de x * x se desbordaría si x es mayor que 46340, puede realizar la llamada a "foo" incondicionalmente. Tenga en cuenta que incluso si fuera aceptable que un programa terminara anormalmente si x está fuera de rango, o que la función devuelva cualquier valor en tales casos, llamar a foo () con un fuera de rango x podría causar daños mucho más allá Cualquiera de esas posibilidades. C tradicional no proporcionaría ningún equipo de seguridad más allá de lo que el programador y la plataforma subyacente suministraron, pero permitiría que el equipo de seguridad limite el daño de situaciones inesperadas. Modern C evitará cualquier equipo de seguridad que no sea 100% efectivo para mantener todo bajo control.