Este es uno de esos casos raros en los que estamos sujetos a las limitaciones del idioma inglés y a la estructura inconsistente del estándar. Entonces, en el mejor de los casos, puedo hacer un contraargumento convincente, ya que es imposible probarlo :) 1
El código de la pregunta muestra un comportamiento bien definido.
Como [7.1.4] es la base de la pregunta, comencemos por ahí:
Cada una de las siguientes declaraciones se aplica a menos que se indique explícitamente lo contrario en las descripciones detalladas que siguen: Si un argumento de una función tiene un valor no válido ( como un valor fuera del dominio de la función, o un puntero fuera del espacio de direcciones del programa, o un puntero nulo , [... otros ejemplos ...] ) [...] el comportamiento no está definido. [... otras declaraciones ...]
Este es un lenguaje torpe. Una interpretación es que los elementos de la lista son UB para todas las funciones de la biblioteca, a menos que se anulen por las descripciones individuales. Pero la lista comienza con "como", lo que indica que es ilustrativa, no exhaustiva. Por ejemplo, no menciona la terminación nula correcta de cadenas (crítica para el comportamiento de eg strcpy
).
Por lo tanto, está claro que la intención / alcance de 7.1.4 es simplemente que un "valor no válido" conduce a UB (a menos que se indique lo contrario ). Tenemos que mirar la descripción de cada función para determinar qué cuenta como "valor no válido".
Ejemplo 1 - strcpy
[7.21.2.3] dice solo esto:
La strcpy
función copia la cadena a la que apunta s2
(incluido el carácter nulo de terminación) en la matriz apuntada por s1
. Si la copia tiene lugar entre objetos que se superponen, el comportamiento no está definido.
No hace mención explícita de punteros nulos, pero tampoco menciona terminadores nulos. En cambio, se infiere de "cadena apuntada por s2
" que los únicos valores válidos son cadenas (es decir, punteros a matrices de caracteres terminadas en nulo).
De hecho, este patrón se puede ver en todas las descripciones individuales. Algunos otros ejemplos:
[7.6.4.1 (fenv)] almacenar el medio ambiente de punto flotante actual en el objeto apuntado porenvp
[7.12.6.4 (frexp)] almacena el entero en el objeto int apuntado porexp
[7.19.5.1 (fclose)] la secuencia apuntada porstream
Ejemplo 2 - printf
[7.19.6.1] dice esto sobre %p
:
p
- El argumento será un puntero a void
. El valor del puntero se convierte en una secuencia de caracteres de impresión, de una manera definida por la implementación.
Null es un valor de puntero válido, y esta sección no menciona explícitamente que null es un caso especial, ni que el puntero tiene que apuntar a un objeto. Por tanto, se define como comportamiento.
1. A menos que se presente un autor de estándares, o que podamos encontrar algo similar a un documento de fundamento que aclare las cosas.