Y at-il un avantage à utiliser la macro WEXITSTATUS en C sur division par 256 au statut exit ()?

StackOverflow https://stackoverflow.com/questions/808541

  •  03-07-2019
  •  | 
  •  

Question

Je faisais un exercice pour l'université où je devais renvoyer une valeur avec sortie, cette valeur étant en fait le compte de quelque chose. Cela pourrait être supérieur à 255 (ce que exit () ne peut pas gérer) mais l'enseignant a suggéré d'utiliser des données de test où le nombre ne pourrait jamais dépasser cette valeur.

Après tout cela, je devais gérer cette valeur, le statut de sortie, j'ai obtenu cette valeur dans le processus principal en utilisant waitpid (). À ma grande surprise, si le processus enfant renvoyait 1, le résultat "réel" la valeur dans le processus principal était 256, 2 était 512 et ainsi de suite ...

J'avais besoin d'imprimer cette valeur, alors je l'ai simplement divisée par 256 et tout a été fait. Toutefois, si j'utilise la macro WEXITSTATUS (), j'obtiendrai également cette valeur comme je le souhaite ...

J'ai regardé le code source C et voici ce que j'ai découvert:

#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)

Je comprends ce qui se passe ici. Par exemple, 512 en binaire correspond à 10 0000 0000, le décalage de 8 o à droite donne 00 0000 0010, soit 2 en décimal. Ce que je ne comprends pas dans cette macro, c’est que & amp; opérateur et le fait que 0xff00 semble un nombre aléatoire (ce n’est probablement pas, d’où vient-il?). Qu'est-ce que cela fait exactement, pourquoi y a-t-il & & amp; 0xff00 " dans la macro? Cela ne fonctionnerait-il pas avec?

Et la vraie question dans ce sujet, est-ce que la même chose que d'appeler cette macro dans mon code est de diviser par 256?

Était-ce utile?

La solution

  

Et la vraie question dans ce sujet,   est la même chose à appeler cette macro   dans mon code comme divisant par 256?

Cela fonctionnera probablement toujours dans les cas où le processus enfant se termine normalement (c'est-à-dire en appelant exit (), et non par une erreur de segmentation, un échec d'assertion, etc.).

Le statut stocké par waitpid () code à la fois la raison pour laquelle le processus enfant a été arrêté et le code de sortie. La raison est stockée dans l'octet de poids faible (obtenu par status & amp; 0xff ) et le code de sortie est stocké dans l'octet suivant (masqué par status & amp; 0xff00 et extrait par WEXITSTATUS () ). Lorsque le processus se termine normalement, la raison est 0 et WEXITSTATUS équivaut à un décalage de 8 (ou une division par 256). Toutefois, si le processus est interrompu par un signal (tel que SIGSEGV), il n’existe aucun code de sortie et vous devez utiliser WTERMSIG pour extraire le numéro du signal de l’octet de cause.

Autres conseils

Si la variable d'état est un entier signé de 16 bits (un "court") sur une machine où "int" est une quantité de 32 bits et si le statut de sortie est compris entre 128..255, alors WEXITSTATUS () vous donne toujours une valeur correcte, où une division par 256 ou un simple décalage vers la droite vous donnera une valeur incorrecte.

Cela est dû au fait que le court-métrage sera étendu à 32 bits et que le masquage annulera l'extension du signe, laissant la valeur correcte (positive) dans le résultat.

Si la machine utilisait des entiers 16 bits, le code dans WEXITSTATUS () changerait probablement puis masquait pour garantir un comportement similaire:

#define WEXITSTATUS(status) (((status)>>8) & 0xFF)

C’est parce que l’implémentation s’occupe de ces détails pour vous que vous devez utiliser la macro WEXITSTATUS ().

Autant que je sache en vérifiant les spécifications Single Unix, votre système stocke le statut de sortie dans le deuxième octet, mais je ne crois pas la norme le fait. Vous devez donc utiliser les macros pour au moins quelques raisons:

  • Ils ont raison. Décaler un nombre négatif fait différentes choses sur différentes plateformes. Cela fonctionne-t-il comme vous le souhaitez sur le vôtre? Je ne sais pas.
  • Ils sont simples. Son efface immédiatement ce que WEXITSTATUS fait. Moins avec d'autres approches. Si vous voyiez la version roulée à la main de WIFSIGNALED , la reconnaîtriez-vous? Combien de temps cela prendrait-il que WIFSIGNALED .
  • Ils sont portables. Comme sa spécification le dit, cela fonctionnera sur tous les systèmes (du moins à peu près tous les systèmes de type Unix).

Ici, 0xff00 est un masque binaire ( texte du lien ). ANDing avec une valeur met tous les bits à zéro, à l'exception du deuxième octet (en partant de la droite).

Vous ne devriez utiliser WEXITSTATUS que sur un processus dont on sait qu'il s'est terminé normalement. Cette information est donnée par la macro WIFEXITED .

  

Et la vraie question dans ce sujet, est-ce que la même chose que d'appeler cette macro dans mon code est de diviser par 256?

La macro rend le code plus lisible et garantit de fonctionner avec n'importe quelle implémentation conforme à Posix. Autant que je sache, Posix ne spécifie pas le format du statut, vous ne pouvez donc pas vous attendre à ce que votre code fonctionne partout.

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