Ci sono motivi per assegnare NULL anziché 0 a variabili non puntatore?

2

L'assegnazione di variabili con valori durante la definizione è una buona pratica.

Una pratica comune è assegnare variabili con 0 e puntatori con NULL.

    int p = NULL; // instead of int p = 0;
    int *ptr = NULL;
    int &ref=p;

Ci sono motivi per assegnare NULL anziché 0 a un tipo di variabile non puntatore? Il codice int p = NULL compila in Visual Studio, ma sembra che potrebbe essere meno leggibile rispetto all'assegnazione a zero.

    
posta evk1206 23.02.2016 - 08:54
fonte

5 risposte

18

La macro NULL è una null- puntatore costante e ha un tipo intero o un tipo di puntatore.

L'utilizzo di NULL per assegnare o inizializzare una variabile senza puntatore portera 'al punto interrogativo di altri programmatori e potrebbe causare errori nel compilatore.
Una riga come

int a = NULL;

è non considerato un buon codice e renderà il codice less leggibile.

    
risposta data 23.02.2016 - 09:32
fonte
7

Penso che la risposta di @R Sahu raggiunga la conclusione giusta, ma le prove a supporto fornite (basate su una singola implementazione) sono alquanto deboli, nel migliore dei casi.

Questo è taggato con entrambe le e . I dettagli di come NULL è definito variano tra i due, e varia anche nel tempo per C ++. In tutti i casi, NULL deve espandersi su una "costante di puntatore nullo definita dall'implementazione". Ciò che varia è la definizione di "costante puntatore nullo".

In C, una costante puntatore nullo deve essere un valore letterale intero con il valore 0 o lo stesso cast per digitare "pointer to void" 1 . Un intero con un valore diverso da zero (di per sé, o cast per digitare "pointer to void") è non consentito 2 . Quindi, 0 , 0L e ((void *)0) sono tutti consentiti, ma qualcosa come ((void *)1234) è non .

In C ++ 98/03, NULL deve anche espandersi a una costante di puntatore nullo - ma con una definizione alquanto diversa del termine - in particolare, la conversione del letterale intero per digitare "pointer to void" è not permesso in C ++ 98/03. Ciò significa che 0 e 0L sono entrambi consentiti (e quindi '(3-(2 + 1))' o, se vuoi essere davvero perverso, nullptr_t .

In C ++ 11, il tipo nullptr e nullptr literal sono stati aggiunti a C ++ e 0 è anche consentito come costante puntatore nullo 3 . NULL può espandersi a qualsiasi costante di puntatore nullo, quindi potrebbe essere 0L , nullptr (ecc.) O NULL , ma (di nuovo) non può essere un numero intero diverso da zero, né può digitare "pointer to void" (o "pointer to char", ecc.)

L' intento , tuttavia, è sempre stato che 0 sia usato solo per rappresentare un puntatore nullo. Sebbene sia C e C ++ consenta che sia definito come un% disadorno% co_de (per un esempio), quindi potrebbe essere possibile assegnarlo a una variabile di tipo int , non vi è alcuna garanzia che il codice che lo fa venga compilato (e un buon numero di persone ritiene che non dovrebbe compilare).

Conclusione: dovresti assegnare sempre solo NULL a un puntatore. Per il nuovo codice, consiglierei di usare NULL solo in C e usando nullptr in C ++. Per il codice C ++ esistente, convertirò in nullptr quando viene eseguito qualsiasi altro refactoring su quel codice, ma di solito non modificherò il codice esclusivamente per cambiare NULL in nullptr ( ma il codice che assegna NULL a qualsiasi tipo di non puntatore dovrebbe essere corretto immediatamente, in C o C ++).

1. La formulazione dello standard C (§6.3.2.3 / 3) recita:

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

Il corsivo (che si trova nell'originale) significa che questa è considerata la definizione di quel termine per questo standard.

2. L'assegnazione di una costante del puntatore nullo a una variabile puntatore può comportare il salvataggio di un valore diverso da zero in tale variabile. Anche se in qualche modo insolito, questo è perfettamente ammissibile. Anche se / quando questo è il caso, tuttavia, il confronto di tale variabile con una costante del puntatore nullo (ad esempio NULL o 0 ) deve produrre true .

Allo stesso modo, un'implementazione è libera di definire qualsiasi numero di altre costanti intere che produrranno un puntatore nullo se assegnato a una variabile puntatore. Ciò non influisce sul requisito su come deve essere definito NULL .

3. Qui, la dicitura ufficiale (da [conv.ptr]) si legge:

A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t.

Anche in questo caso, il corsivo indica che questa è la definizione ufficiale del termine per quello standard.

    
risposta data 23.02.2016 - 19:44
fonte
1

VS 2008 definisce NULL come:

/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

Se stai scrivendo un programma C e usi:

int i = NULL;

che si espanderà a

int i = ((void *)0);

Se qualcuno dovesse scrivere quel codice manualmente, sarei molto sospettoso delle sue abilità uno sviluppatore di software.

Per questo motivo, sconsiglio vivamente l'uso di

int i = NULL;
    
risposta data 23.02.2016 - 16:06
fonte
0

Il puntatore NULL non è richiesto per essere 0. Un'implementazione conforme agli standard potrebbe apparire come questa

#define NULL (void*)0x1234

In secondo luogo il puntatore NULL deve confrontare 0 uguale in un confronto. Quindi l'implementazione dovrebbe garantire che hat if ((void*)0x1234) valga come falso.

Non sono a conoscenza di alcuna implementazione, ma se prevedi che NULL funzioni in modo intercambiabile con 0 sei fuori dalle specifiche C (o C ++).

    
risposta data 23.02.2016 - 17:11
fonte
-4

La risposta breve è no, non devi mai assegnare NULL a una variabile non puntatore.

L'uso di NULL e nullptr in C e C ++ è, IMOSVHO, estremamente sciocco. NULL è definito come 0 o qualche typecast di 0 come ((void *)0) che è davvero la stessa cosa. Per me, 0 significa null. 0 è breve e di facile lettura e può essere utilizzato ovunque tu veda NULL o nullptr in C e C ++.

In lingue come Javascript, il tipo null è un'altra cosa e può essere utile. In JSON si distingue tra nessun valore (vale a dire nulla) e zero che sono due cose diverse. Ma dato che C e C ++ non hanno un tipo nullo, per lo più è inutile.

Alcune persone sostengono che NULL renda il codice più leggibile, ma occupa più spazio sulla tastiera e sullo schermo. Sostengo la coerenza della formattazione del codice, ma anche il codice compatto perché consente di visualizzare più elementi contemporaneamente, semplificando il confronto tra diverse parti del codice. Nonostante tutto, spesso troverai NULL e ora nullptr , dove 0 sarebbe sufficiente, in un codice C e C ++ altrimenti ben scritto.

Quindi il mio consiglio è, non assegnare int s a NULL e non dare la pressione dei pari e assegnare i puntatori a NULL in C o C ++. 0 == NULL .

comp.lang.c FAQ list · Question 5.9

Q: If NULL and 0 are equivalent as null pointer constants, which should I use?

A: Many programmers believe that NULL should be used in all pointer contexts, as a reminder that the value is to be thought of as a pointer. Others feel that the confusion surrounding NULL and 0 is only compounded by hiding 0 behind a macro, and prefer to use unadorned 0 instead. There is no one right answer. (See also questions 9.4 and 17.10.) C programmers must understand that NULL and 0 are interchangeable in pointer contexts, and that an uncast 0 is perfectly acceptable. Any usage of NULL (as opposed to 0) should be considered a gentle reminder that a pointer is involved; programmers should not depend on it (either for their own understanding or the compiler's) for distinguishing pointer 0's from integer 0's.

It is only in pointer contexts that NULL and 0 are equivalent. NULL should not be used when another kind of 0 is required, even though it might work, because doing so sends the wrong stylistic message. (Furthermore, ANSI allows the definition of NULL to be ((void *)0), which will not work at all in non-pointer contexts.) In particular, do not use NULL when the ASCII null character (NUL) is desired. Provide your own definition

#define NUL '%bl0ck_qu0te%'

if you must.

References: K&R1 Sec. 5.4 pp. 97-8 K&R2 Sec. 5.4 p. 102

    
risposta data 14.02.2018 - 22:54
fonte

Leggi altre domande sui tag