En programación informática , el comportamiento no especificado es un comportamiento que puede variar en diferentes implementaciones de un lenguaje de programación . [ aclaración necesaria ] Se puede decir que un programa contiene un comportamiento no especificado cuando su código fuente puede producir un ejecutable que exhibe un comportamiento diferente cuando se compila en un compilador diferente , o en el mismo compilador con diferentes configuraciones, o de hecho en diferentes partes del mismo ejecutable. Si bien los respectivos estándares o especificaciones del lenguaje pueden imponer una variedad de comportamientos posibles, el comportamiento exacto depende de la implementación y puede no determinarse completamente al examinar el código fuente del programa. [1] El comportamiento no especificado a menudo no se manifestará en el comportamiento externo del programa resultante, pero a veces puede conducir a diferentes salidas o resultados, lo que potencialmente causa problemas de portabilidad .
Para permitir que los compiladores produzcan código óptimo para sus respectivas plataformas de destino, los estándares de lenguaje de programación no siempre imponen un cierto comportamiento específico para una construcción de código fuente dada. [2] No definir explícitamente el comportamiento exacto de cada programa posible no se considera un error o debilidad en la especificación del lenguaje, y hacerlo sería inviable. [1] En los lenguajes C y C++ , dichas construcciones no portables generalmente se agrupan en tres categorías: definidas por la implementación, no especificadas y comportamiento no definido . [3]
La definición exacta de comportamiento no especificado varía. En C++, se define como "comportamiento, para una construcción de programa bien formada y datos correctos, que depende de la implementación". [4] El estándar C++ también señala que generalmente se proporciona el rango de comportamientos posibles. [4] A diferencia del comportamiento definido por la implementación, no existe ningún requisito para que la implementación documente su comportamiento. [4] De manera similar, el estándar C lo define como un comportamiento para el cual el estándar "proporciona dos o más posibilidades y no impone requisitos adicionales sobre cuál se elige en cualquier instancia". [5] El comportamiento no especificado es diferente del comportamiento indefinido . Este último es típicamente el resultado de una construcción de programa o datos erróneos, y no se imponen requisitos sobre la traducción o ejecución de tales construcciones. [6]
C y C++ distinguen entre comportamiento definido por la implementación y comportamiento no especificado. En el caso del comportamiento definido por la implementación, la implementación debe elegir un comportamiento particular y documentarlo. Un ejemplo en C/C++ es el tamaño de los tipos de datos enteros. La elección del comportamiento debe ser coherente con el comportamiento documentado dentro de una ejecución determinada del programa.
Muchos lenguajes de programación no especifican el orden de evaluación de las subexpresiones de una expresión completa . Este no determinismo puede permitir implementaciones óptimas para plataformas específicas, por ejemplo, para utilizar paralelismo. Si una o más de las subexpresiones tienen efectos secundarios , entonces el resultado de evaluar la expresión completa puede ser diferente dependiendo del orden de evaluación de las subexpresiones. [1] Por ejemplo, dado
a = f ( b ) + g ( b );
, donde f
y g
modifican ambos b
, el resultado almacenado en a
puede ser diferente dependiendo de si f(b)
o g(b)
se evalúa primero. [1] En los lenguajes C y C++, esto también se aplica a los argumentos de función. Ejemplo: [2]
#include <iostream> int f () { std :: cout << "En f \n " ; devolver 3 ; } int g () { std :: cout << "En g \n " ; devolver 4 ; } int suma ( int i , int j ) { devolver i + j ; } int main () { devolver suma ( f (), g ()); }
El programa resultante escribirá sus dos líneas de salida en un orden no especificado. [2] En otros lenguajes, como Java , el orden de evaluación de los operandos y los argumentos de las funciones está definido explícitamente. [7]