c++ - ¿Es un comportamiento no especificado para comparar punteros a diferentes matrices para la igualdad?
pointers standards (3)
Como hay confusión en la semántica de conformidad, estas son las reglas para C ++. C usa un modelo de conformidad completamente diferente.
El comportamiento indefinido es un término oximorónico, significa que el traductor, NO su programa, puede hacer lo que le plazca. Esto generalmente significa que puede generar código que también hará lo que le plazca (pero eso es una deducción). Cuando el estándar dice que el comportamiento no está definido, el texto en realidad no tiene importancia para el usuario en el sentido de que eludir este texto no cambiará los requisitos que el estándar impone a los traductores.
Un programa mal formado significa que, a menos que se especifique lo contrario, el comportamiento del traductor está rígidamente definido: se requiere rechazar su programa y emitir un mensaje de diagnóstico. El caso especial principal aquí es la Regla de una sola definición, si infringe que su programa está mal formado, pero no se requiere diagnóstico.
La implementación definida impone un requisito al traductor que contenga documentación que especifique el comportamiento explícitamente. En este caso especial, el comportamiento indefinido puede ser el resultado, pero debe indicarse explícitamente.
No especificado es un término estúpido que significa que el comportamiento proviene de un conjunto. En este sentido, bien definido es solo un caso especial donde el conjunto de comportamientos permitidos contiene solo un elemento. No especificado no requiere documentación, por lo que en cierto sentido también significa lo mismo que la implementación definida sin documentación.
En general, el estándar de C ++ no es un estándar de idioma, es un modelo para un estándar de lenguaje. Para generar un estándar real, debe conectar varios parámetros. El más fácil de reconocer es la implementación de límites definidos.
Hay un par de conflictos tontos en el estándar, por ejemplo, un traductor legítimo puede rechazar cada programa C ++ aparentemente bueno sobre la base de que se le solicita que proporcione una función main()
pero el traductor solo admite identificadores de 1 carácter. Este problema se resuelve con la noción de QOI o calidad de implementación. Básicamente dice, a quién le importa, nadie va a comprar ese compilador solo porque es conforme.
Técnicamente, la naturaleza no especificada del operator <
cuando los punteros son para objetos no relacionados probablemente signifique que obtendrás algún tipo de resultado que sea verdadero o falso, pero tu programa no se bloqueará, sin embargo, este no es el significado correcto de no especificado. entonces eso es un Defecto: no especificado impuso una carga a los escritores de Estándares para documentar el conjunto de comportamientos permitidos porque si el conjunto está abierto, entonces es equivalente a un comportamiento indefinido.
De hecho, propuse la solución estándar para el problema de que algunas estructuras de datos requieren que las claves estén totalmente ordenadas, pero los indicadores no están totalmente ordenados por el operator <
. En la mayoría de las máquinas que utilizan direccionamiento lineal, less
es lo mismo que <
, pero la less
operación en, por ejemplo, un procesador x86 es potencialmente más costosa.
Los operadores de igualdad tienen las restricciones semánticas de los operadores relacionales en los punteros:
Los operadores == (igual a) y! = (No igual a) tienen las mismas restricciones semánticas, conversiones y tipo de resultado que los operadores relacionales, excepto por su menor precedencia y el resultado del valor de verdad. [C ++ 03 §5.10p2]
Y los operadores relacionales tienen una restricción para comparar punteros:
Si dos punteros p y q del mismo tipo apuntan a diferentes objetos que no son miembros del mismo objeto o elementos de la misma matriz o a diferentes funciones, o si solo uno de ellos es nulo, los resultados de p <q, p > q, p <= q y p> = q no están especificados. [§5.9p2]
¿Es esto una restricción semántica que es "heredada" por los operadores de igualdad?
Específicamente, dado:
int a[42];
int b[42];
Está claro que (a + 3) <(b + 3) no está especificado, pero es (a + 3) == (b + 3) también no especificado?
La semántica para op==
y op!=
Explícitamente dicen que el mapeo es a excepción de su resultado de valor de verdad . Entonces, debe buscar lo que se define por su resultado de valor de verdad. Si dicen que el resultado no está especificado, entonces no está especificado. Si definen reglas específicas, entonces no lo es. Dice en particular
Dos punteros del mismo tipo se comparan igual si y solo si son ambos nulos, ambos apuntan a la misma función, o ambos representan la misma dirección
El resultado de los operadores de igualdad ( ==
y !=
) Produce resultados especificados siempre que los punteros sean para objetos del mismo tipo. Dando dos punteros al mismo tipo, exactamente uno de los siguientes es verdadero:
- ambos son punteros nulos y se comparan entre sí.
- ambos son indicadores del mismo objeto y se comparan entre sí.
- son punteros a diferentes objetos y no se comparan entre sí.
- al menos uno no se inicializa, y el resultado de la comparación no se define (y, de hecho, la comparación en sí misma puede no ocurrir nunca, simplemente tratando de leer el puntero para hacer la comparación da un comportamiento indefinido).
Bajo las mismas restricciones (ambos punteros son para el mismo tipo de objeto) el resultado de los operadores que ordenan ( <
, <=
, >
, >=
) solo se especifica si ambos son punteros al mismo objeto, o a objetos separados en la misma matriz (y para este propósito, un "trozo" de memoria asignado con malloc
, new
, etc., califica como una matriz). Si los punteros se refieren a objetos separados que no son parte de la misma matriz, el resultado no se especifica. Si uno o ambos punteros no se han inicializado, tiene un comportamiento indefinido.
A pesar de eso, sin embargo, las plantillas de comparación en la biblioteca estándar ( std::less
, std::greater
, std::less_equal
y std::greater_equal
) producen un resultado significativo, incluso cuando / si los operadores integrados lo hacen no. En particular, están obligados a generar un pedido total. Como tal, puede obtener pedidos si lo desea, pero no con los operadores de comparación incorporados (aunque, por supuesto, si uno o ambos punteros no están inicializados, el comportamiento aún no está definido).