In che modo l'inizializzazione del valore "int * ptr = int ()" non è illegale?


86

Il seguente codice (preso da qui ):

int* ptr = int();

compila in Visual C ++ e inizializza il valore del puntatore.

Come è possibile? Voglio dire, int()restituisce un oggetto di tipo inte non posso assegnare un inta un puntatore.

In che modo il codice sopra non è illegale?


Non una risposta, ma un'ottima domanda! Non ho mai visto una cosa del genere.
Josh

6
Poiché le primitive hanno un 'costruttore' in C ++, int()restituisce il valore costruito valore di int(che è penso sia una cosa specificata da C ++ 03) e il valore predefinito di intè 0. Equivale aint *ptr = 0;
wkl

7
@EmanuelEy: No, qualsiasi costante intera a valore zero può essere utilizzata come costante del puntatore nullo, indipendentemente da come i puntatori vengono effettivamente implementati.
Mike Seymour

1
@ MoooingDuck: non ho detto che NULLpotrebbe essere un valore diverso da zero. Ho detto che potrebbe essere qualsiasi costante intera a valore zero (che include int()).
Mike Seymour

5
@DanielPryden Questo è un uso della parola "oggetto" di cui prima non ero a conoscenza.
birichino

Risposte:


110

int()è un'espressione costante con un valore di 0, quindi è un modo valido per produrre una costante puntatore nullo. In definitiva, è solo un modo leggermente diverso di direint *ptr = NULL;


3
+1, il bit di espressione costante è importante e manca dalle prime 2 risposte votate.
David Rodríguez - dribeas

questo va via con C ++ 0x?
Neil G

@ NeilG: questo rimane lo stesso in C ++ 11, anche se ora c'è anche un nullptr, che puoi usare al posto 0o NULLnel nuovo codice.
Jerry Coffin

2
@ Nils: chiarezza del codice e dichiarazione delle proprie intenzioni tramite codice. Ovviamente, con C ++ 11, ora vuoi usare nullptr perché aggiunge anche il vantaggio di controlli extra in fase di compilazione nel mix.
Jamin Grey,

3
@Nils perché ovviamente 0potrebbe significare una costante puntatore nullo o il numero 0, mentre nullptrè ovvio una costante puntatore nullo. Inoltre, come ha detto Jamin, ha anche "controlli extra in fase di compilazione". Prova a pensare prima di digitare.
Miglia in rotta

35

Perché int()rende 0, che è intercambiabile con NULL. NULLstesso è definito come 0, a differenza di C NULLche è (void *) 0.

Nota che questo sarebbe un errore:

int* ptr = int(5);

e questo funzionerà ancora:

int* ptr = int(0);

0è un valore costante speciale e come tale può essere trattato come un valore di puntatore. Espressioni costanti che producono 0, come quelle 1 - 1consentite come costanti puntatore nullo.


1
Si noti inoltre che NULL di C non è necessariamente (void *)0neanche. È semplicemente un'implementazione definita "espressione costante intera con valore 0, o un'espressione di questo tipo espressa per digitare void *".
Jerry Coffin

@ JerryCoffin Non ho mai usato un compilatore C definito NULLcome (void*)0; era sempre 0(o forse 0L). (Ma poi, quando C90 è diventato (void*)0legale in C, stavo già usando C ++.)
James Kanze

1
@JamesKanze: In ubuntu 11.04 e nella nostra versione di Linux, libio.h contiene: #if !defined(__cplusplus) \n #define NULL ((void*)0) \n #else \n #define NULL (0)la versione corrente di gcc in ubuntu è la 4.5, nel nostro sistema è la 4.0.
David Rodríguez - dribeas

5
" 0è un letterale speciale" - solo perché è un'espressione costante e ha il valore speciale 0. (1-1)è ugualmente speciale, è anche una costante puntatore nullo, e così è int(). Il fatto di 0essere letterale è condizione sufficiente ma non necessaria per essere un'espressione costante. Qualcosa di simile strlen(""), sebbene abbia anche il valore speciale 0, non è un'espressione costante e quindi non è una costante puntatore nullo.
Steve Jessop

@SteveJessop: sono d'accordo sulla correzione, si tratta davvero del valore costante 0, non del 0letterale.
Blagovest Buyukliev

18

L'espressione int()restituisce un numero intero inizializzato di default costante, che è il valore 0. Quel valore è speciale: viene utilizzato per inizializzare un puntatore allo stato NULL.


2
Manca un dettaglio molto importante presente nella risposta di Jerry: non è sufficiente che l'espressione restituisca il valore 0, ma deve essere anche un'espressione costante . Per un controesempio, con int f() { return 0; }, l'espressione f()restituisce il valore 0, ma non può essere utilizzata per inizializzare un puntatore.
David Rodríguez - dribeas

@ DavidRodríguez-dribeas, nella mia fretta di presentare una risposta nei termini più semplici possibili ho tralasciato quella parte. Spero sia accettabile adesso.
Mark Ransom

13

Da n3290 (C ++ 03 usa testo simile), 4.10 Conversioni puntatore [conv.ptr] paragrafo 1 (l'enfasi è mia):

1 Una costante puntatore nullo è un'espressione costante integrale (5.19) prvalue di tipo intero che restituisce zero o un prvalue di tipo std :: nullptr_t. Una costante puntatore nullo può essere convertita in un tipo puntatore; il risultato è il valore del puntatore nullo di quel tipo ed è distinguibile da ogni altro valore del puntatore a oggetto o dal tipo di puntatore a funzione. Tale conversione è chiamata conversione del puntatore nullo. [...]

int()è una tale espressione costante integrale prvalue di tipo intero che restituisce zero (è un boccone!), e quindi può essere utilizzata per inizializzare un tipo di puntatore. Come puoi vedere, 0non è l'unica espressione integrale con un caso speciale.


4

Beh int non è un oggetto.

Credo che quello che sta succedendo qui sia che stai dicendo all'int * di puntare a un indirizzo di memoria determinato da int ()

quindi se int () crea 0, int * punterà all'indirizzo di memoria 0


1
int()sicuramente è un oggetto.
Gare di leggerezza in orbita

@Tomalak: non credo che lo sia. È un temporaneo di tipo non di classe e penso di aver ragione nel dire che questi non sono oggetti per quanto riguarda lo standard C ++. È un po 'strano, tuttavia, la sezione sugli "oggetti temporanei" inizia parlando attentamente solo di temporanei di tipo classe, ma in seguito parla di riferimenti vincolanti e, naturalmente, puoi associare un riferimento a int(). Definire int i;, quindi nessuna domanda, iè un oggetto.
Steve Jessop

@Steve: Mi aspetterei solo di discutere su questo in quanto gli "oggetti" sono una regione di archiviazione in C ++ e i provvisori non hanno realmente spazio di archiviazione, giusto? 1.8 / 1 non elenca esplicitamente i provvisori, ma sembra che l'intento sia lì per includerli.
Gare di leggerezza in orbita

1
@ Tomalak: sì, in effetti, i provvisori di tipo non di classe non hanno bisogno di spazio di archiviazione a meno che non si prenda un riferimento. Non importa però, non importa molto. L'affermazione "well int non è un oggetto" è vera solo perché intè un tipo, non un oggetto. Se int()restituisce un oggetto o solo un valore non influisce su nulla che qualcuno abbia detto altrove.
Steve Jessop

@Steve: è indiscutibile :)
Gare di leggerezza in orbita
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.