2012-09-30 16 views
7

Durante il test per NULL, vedo un sacco di codice che utilizza !var. C'è un motivo per utilizzare questo tipo di test rispetto al più esplicito var == NULL. Allo stesso modo, if (var) dovrebbe essere un test corretto per un articolo non null?Dovrebbe essere usato `! Var` o` var == NULL`?

+0

Per ragioni formali, preferisco quest'ultimo - rende l'intento più chiaro. Ma entrambi sono accettabili. –

+0

Trovato una domanda molto simile: http://stackoverflow.com/questions/459743/is-null-always-false – Matt

+0

possibile duplicato di [C/C++ Checking per il puntatore NULL] (http://stackoverflow.com/questions/ 3825668/cc-checking-per-null-pointer) –

risposta

11

La differenza tra:

!var

e

var == NULL

è nel secondo caso il compilatore devono emettere una diagnosi se var non è di tipo puntatore e NULL è definito con un cast (come (void *) 0).

Inoltre, come indicato da @ bitmask nei commenti, per utilizzare la macro NULL, è necessario includere un'intestazione standard che definisca la macro NULL. In C la macro NULL è definita in diverse intestazioni per comodità (come stddef.h, stdio.h, stdlib.h, string.h, ecc.).

Altrimenti le due espressioni sono equivalenti ed è solo una questione di gusti. Usa quello che ti senti più a tuo agio.

E per la seconda domanda if (var) corrisponde a if (var != NULL) con la differenza sopra indicata.

+2

Si noti che è necessario definire almeno una delle diverse intestazioni per 'NULL'. – bitmask

+0

@ bitmask buon punto, lo aggiungo alla mia risposta. – ouah

+0

http://c-faq.com/null/ptrtest.html dice 'if (var) è equivalente a if (var! = 0)' e molto più roba sui puntatori nulli. Inoltre, questa domanda non è già stata posta? vedi http://stackoverflow.com/a/3825704/1273830 è diverso somehome? – Prasanth

2

I ISO/IEC 9899 norma stabilisce che:

  1. come del linguaggio: una costante espressione intera con il valore 0, o una tale espressione fuso al tipo void *, è chiamato un puntatore nullo costante. Se una costante del puntatore nullo viene convertita in un tipo di puntatore, il puntatore risultante, chiamato puntatore nullo, viene garantito per confrontare non uguale a un puntatore a qualsiasi oggetto o funzione.

  2. come da librerie: NULL è una macro che si espande alla costante del puntatore nullo definita dall'implementazione.

Ciò significa che le espressioni fornite sono ugualmente "corrette". La ragione per preferire una forma piuttosto che un'altra è in gran parte una questione di gusti.

+0

Cioè, se si dispone di un compilatore minimo senza avvisi oltre a quanto richiesto dallo standard. Se ne hai uno moderno, diciamo uno realizzato dopo il 1991, riceverai gli avvisi del compilatore se provassi a confrontare una variabile non puntatore con NULL. – Lundin

+0

Ecco perché abbiamo: 'gcc -w' – geocar

2

Dalla norma C:

tipi aritmetici e tipi di puntatore sono chiamati collettivamente tipi scalari.

L'operando dell'operatore unario + o - deve essere di tipo aritmetico; dell'operatore ~, tipo intero; del! operatore, tipo scalare.

Il risultato dell'operatore di negazione logica! è 0 se il valore del suo operando confronta non uguale a 0, 1 se il valore del suo operando è uguale a 0. Il risultato ha tipo int. L'espressione! E è equivalente a (0 == E).

Quindi, questo dovrebbe rispondere alla tua domanda.

+0

In realtà no, a meno che tu non sappia come viene definito' NULL'. –

2

La versione == NULL ha un vantaggio importante: consente al compilatore e agli analizzatori statici di trovare un particolare bug comune.

Supponiamo che "var" non sia un puntatore, ma una variabile allocata. if(!var) sarebbe quindi un bug che passava inosservato.

NULL è spesso dichiarato come #define NULL ((void*)0). Questa dichiarazione non è obbligatoria per lo standard, ma uno dei più comuni. Un compilatore di tipo semidecente controllo sarebbe quindi in grado di produrre un avvertimento per codice come questo:

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

Oltre al vantaggio di cui sopra, è anche stilisticamente corretto non utilizzare l'operatore !, dato che è un operatore logico, pensato per essere usato su variabili booleane, non puntatori. Funziona solo perché C non ha una digitazione forte.

Suggerirei di seguire MISRA-C in questa materia, che impone di rendere espliciti i controlli su NULL o zero. if(x != NULL) anziché if(x). Il fondamento logico di queste regole è un codice più leggibile. Si traduce comunque nello stesso codice macchina, quindi non c'è nulla di male nel rendere il codice più facile da leggere.

Problemi correlati