2012-09-30 40 views
7

Cuando se prueba para NULL, veo un montón de código que usa !var. ¿Hay alguna razón para usar este tipo de prueba en comparación con el más explícito var == NULL? ¿Igual sería if (var) ser una prueba correcta para que un artículo sea no nulo?¿Deberían usarse `! Var` o` var == NULL`?

+0

Por razones formales, prefiero este último: hace que la intención sea más clara. Pero cualquiera es aceptable. –

+0

Encontré una pregunta muy similar: http://stackoverflow.com/questions/459743/is-null-always-false – Matt

+0

posible duplicado de [C/C++ Comprobación para el puntero NULL] (http://stackoverflow.com/questions/ 3825668/cc-checking-for-null-pointer) –

Respuesta

11

La diferencia entre:

!var

y

var == NULL

está en el segundo caso el compilador tiene que emitir un diagnóstico si var no es de un tipo de puntero y NULL es definido con un molde (como (void *) 0).

También (como lo señala @bitmask en los comentarios) para usar la macro NULL, debe incluir un encabezado estándar que defina la macro NULL. En C, la macro NULL se define en varios encabezados por conveniencia (como stddef.h, stdio.h, stdlib.h, string.h, etc.).

De lo contrario, las dos expresiones son equivalentes y es solo una cuestión de gusto. Usa el que te sientas más cómodo.

Y para su segunda pregunta if (var) es lo mismo que if (var != NULL) con la diferencia mencionada anteriormente.

+2

Tenga en cuenta que necesita definir al menos uno de los varios encabezados para 'NULL'. – bitmask

+0

@bitmask buen punto, lo agrego a mi respuesta. – ouah

+0

http://c-faq.com/null/ptrtest.html dice 'if (var) es equivalente a if (var! = 0)' y muchas más cosas sobre null punteros. ¿No es esta pregunta ya hecha? ver http://stackoverflow.com/a/3825704/1273830 ¿es diferente alguna casa? – Prasanth

2

Los ISO/IEC 9899 estados estándar que:

  1. como de la lengua: una expresión constante entera con el valor 0, o una expresión tal fundido para escribir void *, se llama una constante puntero nulo. Si una constante de puntero nulo se convierte en un tipo de puntero, se garantiza que el puntero resultante, llamado puntero nulo, se compare desigual a un puntero a cualquier objeto o función.

  2. de las bibliotecas: NULL es una macro que se expande a la constante del puntero nulo definido por la implementación.

Eso significa que las expresiones que usted da son igualmente "correctas". La razón para preferir una forma sobre otra es en gran medida una cuestión de gusto.

+0

Es decir, si tiene un compilador mínimo sin advertencias más allá de lo requerido por el estándar. Si tiene uno moderno, digamos uno hecho después de 1991, obtendría advertencias del compilador si tratara de comparar una variable no apuntadora contra NULL. – Lundin

+0

Es por eso que tenemos: 'gcc -w' – geocar

2

Desde el estándar C:

tipos aritméticos y los tipos de puntero se denominan colectivamente tipos escalares.

El operando del operador unario + o - debe tener un tipo aritmético; del operador ~, tipo entero; del ! operador, tipo escalar.

¡El resultado del operador de negación lógica! es 0 si el valor de su operando se compara desigual a 0, 1 si el valor de su operando se compara con 0. El resultado tiene el tipo int. La expresión! E es equivalente a (0 == E).

Por lo tanto, eso debería responder a su pregunta.

+0

Realmente no, a menos que sepa cómo' NULL' se define. –

2

La versión var == NULL tiene una gran ventaja: hace posible que el compilador y los analizadores estáticos encuentren un error común en particular.

Supongamos que "var" no es un puntero, sino una variable asignada. if(!var) sería un error que pasa desapercibido.

NULL a menudo se declara como #define NULL ((void*)0). Esta declaración no es obligatoria según el estándar, sino una de las más comunes. Un compilador con la comprobación de tipos medio decente sería entonces capaz de producir una advertencia de código como este:

int var = ...; 
if(var == NULL) // compiler warning, var is not a pointer 

Aparte de la ventaja anterior, también es estilísticamente correcto no usar el operador !, ya que es una operador lógico, destinado a ser utilizado en variables booleanas, no punteros. Simplemente funciona, ya que C no tiene un tipado fuerte.

Recomendaría seguir a MISRA-C en este asunto, que establece que las comprobaciones contra NULL o cero deben hacerse explícitas. if(x != NULL) en lugar de if(x). El fundamento de esas reglas es un código más legible. Se traduce en el mismo código de máquina de todos modos, por lo que no hay ningún problema en hacer que su código sea más fácil de leer.