Question

Quelques éléments d’arrière-plan: si je souhaitais utiliser, par exemple, scanf() pour convertir une chaîne en un type entier standard, comme uint16_t, je & # 8217; j'utiliserais SCNu16 à partir de <inttypes.h> , comme ceci:

#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);

Mais un type entier plus rare, comme pid_t, n’a pas une telle chose; seuls les types entiers normaux sont pris en charge par printf(). Pour convertir l’autre manière, en intmax_t un PRIdMAX, je peux le transtyper en <=> et utiliser <=>, comme ceci:

#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);

Cependant, il ne semble pas y avoir de moyen de transférer <=> dans un <=>. Voici donc ma question: comment faire cela de manière portable?

#include <stdio.h>
#include <sys/types.h>
pid_t x;
char *xs = 17;
sscanf(xs, "%u", &x);  /* Not portable! pid_t might not be int! /*

J'ai pensé à <=> passer à un <=> et à vérifier ensuite que la valeur est dans les limites de <=> & # 8217; s avant de passer à <=>, mais il ne semble pas y avoir de moyen pour obtenir les valeurs maximales ou minimales pour <=>.

Était-ce utile?

La solution

Il existe une solution robuste et portable qui consiste à utiliser strtoimax() et à vérifier les débordements.

C’est-à-dire que j’analyse un intmax_t, cherche une erreur dans pid_t, puis vérifie également si elle & "; correspond à &"; dans un scanf() en le lançant et en le comparant à la strtoll() valeur d'origine.

#include <inttypes.h>
#include <stdio.h>
#include <iso646.h>
#include <sys/types.h>
char *xs = "17";            /* The string to convert */
intmax_t xmax;
char *tmp;
pid_t x;                    /* Target variable */

errno = 0;
xmax = strtoimax(xs, &tmp, 10);
if(errno != 0 or tmp == xs or *tmp != '\0'
   or xmax != (pid_t)xmax){
  fprintf(stderr, "Bad PID!\n");
} else {
  x = (pid_t)xmax;
  ...
}

Il n'est pas possible d'utiliser <=> car, comme je l'ai dit dans un commentaire, <=> ne détectera pas les débordements . Mais j’ai eu tort de dire qu’aucune des fonctions liées à <=> ne prend une <=>; <=> fait!

Cela ne fonctionnera pas non plus d'utiliser <=> si vous ne connaissez pas la taille de votre type entier (<=>, dans ce cas).

Autres conseils

Cela dépend de votre capacité à être portable. POSIX indique que pid_t est un type entier signé utilisé pour stocker les ID de processus et les ID de groupes de processus. En pratique, vous pouvez supposer en toute sécurité que long est suffisamment grand. A défaut, votre intmax_t doit être suffisamment grand (il acceptera donc tout <inttypes.h> valide); le problème est que ce type pourrait accepter des valeurs qui ne sont pas légitimes dans <unistd.h>. Vous êtes coincé entre le marteau et l'enclume.

Je voudrais utiliser <sys/types.h> et ne pas trop m'inquiéter à ce sujet, sauf pour un obscur commentaire quelque part qu'un archéologue logiciel de 100 ans va trouver et observer donne une raison pour laquelle le processeur 256 bits s'arrête de fonctionner lorsqu'il est remis une valeur de 512 bits sous forme de <=>.

POSIX 1003.1-2008 est maintenant disponible sur le Web (tout 3872 pages de celui-ci, en PDF et HTML). Vous devez vous inscrire (gratuit). J'y suis parvenu à la Librairie de groupe ouvert .

Tout ce que je vois ici, c'est qu'il doit s'agir d'un type entier signé. De toute évidence, toutes les valeurs d’entiers signés valides entrent dans <=>. Je ne trouve aucune information dans <=> ou <=> qui indique PID_T_MAX ou PID_T_MIN ou d'autres valeurs de ce type (mais je viens juste d'y avoir accès ce soir, elle pourrait donc être masquée là où je ne l'ai pas recherchée) . OTOH, je maintiens mon commentaire initial - je pense que les valeurs 32 bits sont adéquates d'un point de vue pratique, et j'utiliserais de toute façon <=>, ce qui serait 64 bits sur des machines 8 bits. Je suppose que la pire chose qui puisse arriver, c’est qu’un processus «privilégié de manière appropriée» lise une valeur trop grande et envoie un signal au mauvais processus en raison d’une incompatibilité de types. Je ne suis pas convaincu que cela m'inquiète.

... oooh! ... p400 sous <=>

  

L’implémentation doit prendre en charge un ou plusieurs environnements de programmation dans lesquels les largeurs   blksize_t, pid_t, size_t, ssize_t et suseconds_t ne dépassent pas la largeur du type long.

Si vous êtes vraiment inquiet, vous pouvez _assert(sizeof(pid_t) <= long) ou le type de votre choix pour votre "%".

Comme expliqué dans le cette réponse , la spécification indique signed int. Si 'int' change, votre '% u' change par définition avec lui.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top