2009-12-04 15 views
22

Un altro semplice esempio:Perché restituire un errore negativo? (Ad esempio restituire -EIO)

if (wpa_s->mlme.ssid_len == 0) 
    return -EINVAL; 

Perché il meno unario? Questo è (di solito) fatto per funzioni che restituiscono> 0 in caso di successo e < (=) 0 in caso di errore o c'è qualche altro motivo?

+29

Perché non ci piace niente di meno che il SUCCESSO! –

+2

Non capisco perché la gente metta un tag "[C]" nel titolo di una domanda. Ogni domanda collega sempre quali sono i suoi tag (ad esempio la domanda è attualmente taggata [c], [errno], [valore di ritorno]. Perché non hai intitolato la domanda "[C] [errno] [valore di ritorno] Perché restituire un errore negativo? (es. return -EIO) "??? – Pete

+0

Ho visto il titolo della domanda e immediatamente ho avuto un attacco, seguito da un profondo coma. Se non avessi un gruppo di risposta rapida di chirurghi cerebrali di livello mondiale su le mie premesse in ogni momento, chissà se mi sono ripreso in tempo per rispondere alla domanda? –

risposta

13

Questo è fondamentalmente le ragioni. Molte funzioni hanno molti risultati positivi "buoni", quindi lascia i valori negativi per i codici di errore.

I codici di errore C/POSIX sono un po '"storicamente cresciuti", quindi non ha molto senso tentare di attribuire troppo rima o ragione a loro.

Molte più lingue moderne generano eccezioni per errori in modo che non debbano dirottare parte del loro possibile intervallo di risposta per i codici di errore. Ovviamente ci sono dei compromessi in entrambi i casi.

+7

C'era almeno una tendenza a definire 0 come successo, positivo come successo con i problemi, e negativo come non riuscito - almeno nei miei vecchi giorni Unix. –

7

La tua comprensione è ampiamente corretta. L'interpretazione ovvia è quella giusta.

La convenzione standard è leggermente diversa dalla formula, tuttavia.

In Unix, un programma che termina con 0 test di stato come vero o successo di utilità CLI-livello come il guscio. Nella libreria, -1 generalmente restituisce un errore.

Questo porta ad un paradigma generale in cui >= 0 significa buona e < 0 significa errore. Nessuno di questi è impostato in pietra.

BTW, questo potrebbe essere classificato come il sentinel pattern e si potrebbe chiamare un ritorno sentinella. In realtà è una combinazione di un "valore" sentinella e un codice di errore, ed è più facile da digitare e più facile da rendere thread-safe che restituire un codice di errore in un posto e un valore sentinella per errore in un altro.

Wikipedia reports that a sentinel value viene utilizzato per terminare un ciclo, ma penserei che un ritorno di funzione sarebbe un'istanza molto più comune. Nessuno è precisamente responsabile di queste definizioni.

17

In primo luogo, questa non è proprio una cosa da C. Stai guardando una funzione che è scritta in C per qualche scopo. Le stesse convenzioni potrebbero essere utilizzate in qualsiasi lingua.

Indietro nei miei vecchi giorni Unix, c'era qualcosa di una convenzione che significava 0 successo, un numero positivo significava problemi minori, e un numero negativo significava una sorta di fallimento. Pertanto, c'era anche una sorta di convenzione di if (foo() >= 0) { /* success of a sort */ }.

Questo è stato senza dubbio correlato ai codici di ritorno del processo Unix, dove 0 è stato il successo.

+0

Ti ha citato qui su una domanda simile [Unix e Linux: "Che cosa significa exit 99?"] (Http://unix.stackexchange.com/a/125333/11836) – smci

0

Da una prospettiva di ottimizzazione, l'utilizzo di numeri negativi consente ai kernel basati su Unix di verificare la presenza di un codice di errore utilizzando un solo confronto anziché due.

Le funzioni nel kernel restituiscono spesso i codici di errore al posto dei puntatori.Ciò significa che i codici di errore non possono sovrapporsi a indirizzi di puntatori validi, quindi dovrebbero essere fondamentalmente i valori senza segno più bassi (>= 0) o quelli più alti (<= unsigned max).

Il controllo dei valori di puntatore per NULL e per i codici di errore è un'operazione estremamente comune, quindi è consigliabile ottimizzarli.

Tipicamente fondo valori < 0x8000 sono NULL ed i valori massimi sono codici di errore (ricordiamo che -1 è memorizzato come 0xff...ff, il valore massimo possibile senza segno).

Questo significa che è possibile utilizzare un confronto per verificare la presenza di ciascuno:

NULL se x <= 0x8000 (vero per 0 a 0x8000)

ERRNO se x >= (unsigned long)(-MAX_ERRNO) (vero per -1 a -MAX_ERRNO)

You can see this happening in Linux's err.h file.

Problemi correlati