2009-12-04 21 views
22

Otro ejemplo simple:¿Por qué devolver un error negativo? (Por ejemplo, volver -EIO)

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

Por qué el menos unario? ¿Esto (generalmente) se realiza para las funciones que devuelven> 0 en caso de éxito y < (=) 0 en caso de falla, o existe alguna otra razón?

+29

Porque no nos gusta nada menos que ÉXITO! –

+2

No entiendo por qué las personas ponen una etiqueta "[C]" en el título de una pregunta. Cada pregunta siempre vincula sus etiquetas (por ejemplo, la pregunta está actualmente etiquetada [c], [errno], [return-value]. ¿Por qué no tituló la pregunta "[C] [errno] [return-value]? devolver un error negativo? (por ejemplo, devolver -EIO) "??? – Pete

+0

Miré el título de la pregunta y de inmediato tuve un ataque, seguido de coma profundo. Si no tuviera un equipo de respuesta rápida de cirujanos de cerebro de clase mundial en mis instalaciones en todo momento, ¿quién sabe si me hubiera recuperado a tiempo para responder la pregunta? –

Respuesta

13

Esa es básicamente la razón. Muchas funciones tienen muchos resultados positivos "buenos", por lo que dejan los valores negativos para los códigos de error.

Los códigos de error C/POSIX son un poco "históricamente crecidos", por lo que no tiene mucho sentido tratar de atribuirles demasiado rima o razón.

Muchos idiomas más modernos lanzan excepciones para errores para que no tengan que secuestrar parte de su posible rango de respuesta para códigos de error. Por supuesto, hay compensaciones de cualquier manera.

+7

Al menos solía haber una tendencia a definir 0 como exitoso, positivo como exitoso con problemas y negativo como sin éxito, al menos en mis viejos días en Unix. –

7

Según su conocimiento, es ampliamente correcto. La interpretación obvia es la correcta.

Sin embargo, la convención estándar es ligeramente diferente a su fórmula.

En Unix, un programa que sale con 0 pruebas de estado como cierto éxito o a utilidades CLI nivel como la cáscara. En la biblioteca, -1 suele ser un retorno de error.

Esto conduce a un paradigma general donde >= 0 significa buena y < 0 significa error. Nada de esto está escrito en piedra.

Por cierto, esto podría ser clasificado como el sentinel pattern y se podría llamar un retorno centinela. En realidad, es una combinación de un "valor" de centinela y un código de error, y es más fácil escribir y hacer seguro para subprocesos que devolver un código de error en un lugar y un valor de notificación de error en otro.

Wikipedia reports that a sentinel value se utiliza para terminar un ciclo, pero creo que una función de retorno sería una instancia mucho más común. Nadie está precisamente a cargo de estas definiciones.

17

En primer lugar, esto no es realmente una cosa de C. Está buscando una función escrita en C para algún propósito. Las mismas convenciones podrían usarse en cualquier idioma.

En mi época anterior a Unix, existía una convención de que 0 significaba éxito, un número positivo significaba problemas menores y un número negativo significaba algún tipo de error. Por lo tanto, también hubo una especie de convención de if (foo() >= 0) { /* success of a sort */ }.

Esto sin duda se relacionó con los códigos de retorno de proceso de Unix, donde 0 fue exitoso.

+0

Lo citamos aquí en una pregunta similar [Unix y Linux: "¿Qué significa exit 99?"] (Http://unix.stackexchange.com/a/125333/11836) – smci

0

Desde una perspectiva de optimización, el uso de números negativos permite que los kernels basados ​​en Unix comprueben un código de error usando solo una comparación en lugar de dos.

Las funciones en el kernel devuelven frecuentemente códigos de error en lugar de punteros.Esto significa que los códigos de error no se pueden superponer con direcciones de puntero válidas, por lo que básicamente deben ser los valores sin signo más bajos (>= 0) o los más altos (<= unsigned max).

La comprobación de los valores del puntero para NULL y los códigos de error son operaciones extremadamente comunes, por lo que tiene sentido optimizarlas.

Típicamente la parte inferior valores < 0x8000 son NULL y los valores superiores son códigos de error (recordemos que -1 se almacena como 0xff...ff, el valor sin signo máximo posible).

Esto significa que se puede utilizar una comparación para comprobar si cada uno:

NULL si x <= 0x8000 (válido para 0 a 0x8000)

ERRNO si x >= (unsigned long)(-MAX_ERRNO) (cierto para -1 a -MAX_ERRNO)

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

Cuestiones relacionadas