C'est l'un de ces cas particuliers où nous sommes soumis aux limites de la langue anglaise et à la structure incohérente de la norme. Donc, au mieux, je peux faire un contre-argument convaincant, car il est impossible de prouver le :) 1
Le code de la question présente un comportement bien défini.
Comme [7.1.4] est la base de la question, commençons par là :
Chacune des déclarations suivantes s'applique, sauf mention contraire explicite dans les descriptions détaillées qui suivent : Si un argument d'une fonction a une valeur invalide ( comme une valeur hors du domaine de la fonction, ou un pointeur hors de l'espace d'adressage du programme, ou un pointeur nul , [... autres exemples ...] ) [...] le comportement est indéfini. [... autres déclarations ...]
C'est un langage maladroit. Une interprétation possible est que les éléments de la liste sont l'UB pour toutes les fonctions de la bibliothèque, à moins qu'ils ne soient remplacés par les descriptions individuelles. Mais la liste commence par "telles que", ce qui indique qu'elle est illustrative et non exhaustive. Par exemple, elle ne mentionne pas la terminaison nulle correcte des chaînes de caractères (critique pour le comportement de par ex. strcpy
).
Ainsi, il est clair que l'intention/la portée de 7.1.4 est simplement qu'une "valeur invalide" conduit à UB ( sauf indication contraire ). Il faut se reporter à la description de chaque fonction pour déterminer ce qui est considéré comme une "valeur non valide".
Exemple 1 - strcpy
[7.21.2.3] ne dit que ceci :
El strcpy
copie la chaîne de caractères pointée par s2
(y compris le caractère nul de fin) dans le tableau pointé par s1
. Si la copie a lieu entre des objets qui se chevauchent, le comportement est indéfini.
Il ne mentionne pas explicitement les pointeurs nuls, mais il ne mentionne pas non plus les terminateurs nuls. Au lieu de cela, on déduit de "string pointed to by s2
"que les seules valeurs valides sont des chaînes de caractères (c'est-à-dire des pointeurs vers des tableaux de caractères à terminaison nulle).
En effet, ce schéma se retrouve dans toutes les descriptions individuelles. Quelques autres exemples :
-
[7.6.4.1 (fenv)] stocker l'environnement actuel en virgule flottante dans le objet pointé vers par envp
-
[7.12.6.4 (frexp)] stocker l'entier dans l'int objet pointé vers par exp
-
[7.19.5.1 (fclose)] le site stream pointé vers par stream
Exemple 2 - printf
[7.19.6.1] dit ceci à propos de %p
:
p
- L'argument est un pointeur vers void
. La valeur du pointeur est convertie en une séquence de caractères d'impression, d'une manière définie par l'implémentation.
Null est une valeur de pointeur valide, et cette section ne mentionne pas explicitement que null est un cas spécial, ni que le pointeur doit pointer vers un objet. Il s'agit donc d'un comportement défini.
1. A moins qu'un auteur de normes ne se manifeste, ou que nous trouvions quelque chose de similaire à une <a href="http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf" rel="noreferrer">raisonnement </a>document qui clarifie les choses.
0 votes
En fait, je ne pense pas que quiconque (y compris le comité C) s'en soucie trop. Il s'agit d'un problème tout à fait artificiel, sans signification pratique (ou presque).
0 votes
C'est parce que printf ne fait qu'afficher la valeur, et ne touche pas (dans le sens de la lecture ou de l'écriture de l'objet pointé) - ne peut pas être UB i le pointeur a une valeur valide pour son type (NULL est le valide valeur)
3 votes
@PeterJ disons que ce que vous dites est vrai (bien que la norme stipule clairement le contraire), le seul fait que nous débattons sur ce sujet rend la question valide et correcte, car il semble que la partie de la norme citée ci-dessous rende très difficile la compréhension de ce qui se passe pour un développeur ordinaire. Autrement dit, la question ne mérite pas le vote négatif, car ce problème nécessite une clarification !
1 votes
Relié : stackoverflow.com/q/10461360/694576
0 votes
Non - la lecture du %p standard n'est pas une opération de pointeur, et a été ajoutée uniquement pour la raison que la taille du pointeur peut varier de la taille de l'entier. Il s'agit d'une exception aux règles relatives aux pointeurs.
2 votes
@PeterJ c'est une autre histoire alors, merci pour la clarification :)
0 votes
GCC 5.4 sur Ubuntu 16.04 montre : ( nil ) qui fait référence au premier emplacement de la mémoire. J'imprime p+1 show : 0x1
0 votes
@DrorK. selon la documentaion (1) L'argument est un pointeur vers void. La valeur du pointeur est convertie en une séquence de caractères d'impression, d'une manière définie par l'implémentation. Si une spécification de conversion est invalide, le comportement est indéfini. Si un argument n'est pas du type correct pour la spécification de conversion correspondante, le comportement est indéfini.
0 votes
Voir la réponse à cette question dans le lien ci-dessous. stackoverflow.com/questions/10461360/