Que puis-je supposer sur le comportement de atoi () en cas d’erreur?

La fonction standard de la bibliothèque C atoi est documentée dans ISO 9899: 2011 en tant que:

7.22.1 Fonctions de conversion numériques

1 Les fonctions atof , atoi , atol et atoll n’ont pas besoin d’affecter la valeur de l’expression entière errno lors d’une erreur. Si la valeur du résultat ne peut pas être représentée, le comportement est indéfini.

7.22.1.2 Les fonctions atoi , atol et atoll

Synopsis

 #include  int atoi(const char *nptr); long int atol(const char *nptr); long long int atoll(const char *nptr); 

La description

2 Les fonctions atoi , atol et atoll convertissent la partie initiale de la chaîne pointée par nptr en représentation int , long int et long long int , respectivement. À l’exception du comportement en cas d’erreur, ils sont équivalents à

 atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10) 

Résultats

3 Les fonctions atoi , atol et atoll renvoient la valeur convertie.

Quel est le comportement souhaité lorsque la chaîne pointée par nptr ne peut pas être analysée comme un entier? Les quatre avis suivants semblent exister:

  • Aucune conversion n’est effectuée et zéro est renvoyé. Ceci est la documentation fournie par certaines références comme celle-ci .
  • Le comportement est semblable à celui de strtol sauf que errno peut ne pas être défini. Cela découle de la prise de “À l’exception du comportement en cas d’erreur” en tant que référence au § 7.21.1.
  • Le comportement n’est pas spécifié. Voici ce que dit POSIX :

    L’appel atoi (str) doit être équivalent à:

     (int) strtol(str, (char **)NULL, 10) 

    sauf que le traitement des erreurs peut différer. Si la valeur ne peut pas être représentée, le comportement est indéfini.

    En outre, la section Utilisation de l’application indique:

    La fonction atoi () est englobée par strtol () mais est conservée car elle est largement utilisée dans le code existant. Si le nombre n’est pas connu pour être compris dans la plage, strtol () doit être utilisé car atoi () n’est pas nécessaire pour effectuer une vérification d’erreur.

    Notez que POSIX affirme que la spécification est alignée sur ISO 9899: 1999 (qui contient le même langage que l’ISO 9899: 2011 en ce qui me concerne):

    La fonctionnalité décrite sur cette page de référence est alignée sur la norme ISO C. Tout conflit entre les exigences décrites ici et la norme ISO C est involontaire. Ce volume de POSIX.1-2008 est conforme à la norme ISO C.

    Selon mon membre local du comité POSIX, il s’agit du comportement historique d’UNIX.

  • Le comportement n’est pas défini. Cette interprétation découle du fait que le §7.22.1.2 ¶2 ne dit jamais explicitement ce qui se passe en cas d’erreur. Le comportement qui n’est ni défini, ni explicitement défini par l’implémentation ou non spécifié n’est pas défini.

Laquelle de ces interprétations est correcte? S’il vous plaît essayez de vous référer à la documentation faisant autorité.

Quel est le comportement souhaité lorsque la chaîne pointée par nptr ne peut pas être analysée comme un entier?

Pour être clair, cette question s’applique aux

 // Case 1 value = atoi(""); value = atoi(" "); value = atoi("wxyz"); 

et non ce qui suit:

 // Case 2 // NULL does not point to a ssortingng value = atoi(NULL); // Convert the initial portion, yet has following junk value = atoi("123xyz"); value = atoi("123 "); 

Et peut-être / peut-être pas ce qui suit en fonction de l’utilisation de l’ entier .

 // Case 3 // Can be parsed as an _integer_, yet overflows an `int`. value = atoi("12345678901234567890123456789012345678901234567890"); 

Le comportement “non-cas 2” de ato*() dépend de la signification de l’ erreur dans

Les fonctions atoi , atol et atoll convertissent la partie initiale de la chaîne pointée par nptr en représentation int , long int et long long int , respectivement. À l’exception du comportement en cas d’ erreur , ils sont équivalents à
atoi: (int)strtol(nptr, (char **)NULL, 10)
...
C11dr §7.22.1.2 2


Certainement, erreur comprend le cas 3: “Si la valeur correcte est en dehors de la plage des valeurs pouvant être représentées”. strto*() , bien que peut-être pas ato*() , dans ce cas, définit le numéro d’ erreur errrno défini dans . Puisque la spécification de ato*() ne s’applique pas à cette erreur , le débordement, le résultat, est UB par

Le comportement non défini est indiqué autrement dans la présente Norme internationale par les mots «comportement non défini» ou par l’omission de toute définition explicite du comportement. C11dr §4 2


Pour le cas 1, le comportement de strto*() est bien défini et n’est pas spécifié pour affecter errno . La spécification va dans les détails (§7.22.1.4 4) et appelle ces “pas de conversion”, pas une erreur . Ainsi, il peut affirmer que le strto*() 1 strto*() n’est pas une erreur , mais un “pas de conversion”. Ainsi par …

“Si aucune conversion ne peut être effectuée, la valeur renvoyée est zéro. C11dr §7.22.1.4 8

atoi("") doit renvoyer 0.