Qualche vantaggio nell'uso della macro WEXITSTATUS in C su divisione per 256 allo stato exit ()?

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

  •  03-07-2019
  •  | 
  •  

Domanda

Stavo facendo un esercizio per l'università in cui dovevo restituire un valore con uscita, quel valore era in realtà un conteggio di qualcosa. Potrebbe essere superiore a 255 (che exit () non è in grado di gestire) ma l'insegnante ha suggerito di utilizzare i dati di test in cui il conteggio non potrebbe mai andare oltre tale valore.

Dopo tutto ciò, avevo bisogno di gestire questo valore di conteggio, lo stato di uscita, ho ottenuto questo valore nel processo principale usando waitpid (). Con mia sorpresa, se il processo figlio ha restituito 1, il "reale" il valore nel processo principale era 256, 2 era 512 e così via ...

Avevo bisogno di stampare questo valore, quindi l'ho semplicemente diviso per 256 ed è stato fatto. Tuttavia, se uso la macro WEXITSTATUS (), otterrò anche questo valore nel modo in cui lo voglio ...

Ho guardato il codice sorgente C e questo è quello che ho scoperto:

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

Capisco cosa sta succedendo qui, ad esempio 512 in binario è 10 0000 0000, spostando 8 o a destra si darà 00 0000 0010, che è 2 in decimale. Quello che non capisco in questa macro è che & amp; operatore e il fatto che 0xff00 sembra un numero casuale (probabilmente non lo è, da dove viene però?). Che cosa fa esattamente questo, perché c'è " & amp; 0xFF00 " nella macro? Non funzionerebbe senza?

E la vera domanda in questo argomento, è la stessa cosa per chiamare questa macro nel mio codice come dividere per 256?

È stato utile?

Soluzione

  

E la vera domanda in questo argomento,   è la stessa cosa per chiamare questa macro   nel mio codice come divisione per 256?

Probabilmente funzionerà sempre nei casi in cui il processo figlio termina normalmente (cioè chiamando exit (), non per un errore di segmentazione, errore di asserzione, ecc.)

Lo stato memorizzato da waitpid () codifica sia il motivo per cui il processo figlio è stato terminato sia il codice di uscita. Il motivo viene memorizzato nel byte meno significativo (ottenuto da status & amp; 0xff ) e il codice di uscita viene memorizzato nel byte successivo (mascherato da status & amp; 0xff00 ed estratto da WEXITSTATUS () ). Quando il processo termina normalmente, il motivo è 0 e quindi WEXITSTATUS equivale allo spostamento di 8 (o alla divisione di 256). Tuttavia, se il processo viene interrotto da un segnale (come SIGSEGV), non esiste un codice di uscita e devi utilizzare WTERMSIG per estrarre il numero del segnale dal byte del motivo.

Altri suggerimenti

Se la variabile di stato è un numero intero a 16 bit con segno (un 'corto') su una macchina in cui 'int' è una quantità di 32 bit e se lo stato di uscita è compreso nell'intervallo 128..255, quindi WEXITSTATUS () ti dà ancora un valore corretto dove dividere per 256 o semplicemente spostare a destra ti darà un valore errato.

Questo perché il corto verrà esteso a 32 bit e il mascheramento annulla l'estensione del segno, lasciando il valore corretto (positivo) nel risultato.

Se la macchina utilizzava numeri interi a 16 bit, allora il codice in WEXITSTATUS () probabilmente si spostava quindi maschera per garantire un comportamento simile:

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

È perché l'implementazione si prende cura di tali dettagli per te che dovresti usare la macro WEXITSTATUS ().

Per quanto posso sapere controllando la specifica Unix singola, il tuo sistema memorizza lo stato di uscita nell'ottetto dal secondo alla destra, ma non credo lo standard . Quindi, dovresti usare le macro per almeno alcuni motivi:

  • Sono corretti. Lo spostamento dei bit di un numero negativo fa cose diverse su piattaforme diverse. Funziona come vuoi sul tuo? Non lo so.
  • Sono semplici. È subito chiaro cosa fa WEXITSTATUS . Meno così con altri approcci. Se vedessi la versione arrotolata a mano di WIFSIGNALED , la riconosceresti? Quanto tempo ci vorrebbe rispetto a WIFSIGNALED .
  • Sono portatili. Dal momento che il modo in cui le specifiche dicono di farlo, funzionerà su ogni sistema (almeno praticamente ogni sistema simile a Unix).

Qui 0xff00 è una maschera binaria ( testo del link ). ANDinglo con un valore imposta tutti i bit su zero, tranne il secondo byte (contando da destra).

Dovresti usare WEXITSTATUS su un processo che è noto per essere uscito normalmente. Queste informazioni sono fornite dalla macro WIFEXITED .

  

E la vera domanda in questo argomento, è la stessa cosa per chiamare questa macro nel mio codice come dividere per 256?

La macro rende il codice più leggibile ed è garantito che funzioni su qualsiasi implementazione conforme a Posix. Per quanto ne so Posix non specifica il formato dello stato, quindi non puoi aspettarti che il tuo codice funzioni ovunque.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top