2010-08-13 16 views
35

Sono sempre stato curioso di questo - perché in C++ devo trasmettere il valore di ritorno da malloc ma non in C?Perché il C++ richiede un cast per malloc() ma C no?

Ecco l'esempio in C++ che funziona:

int *int_ptr = (int *)malloc(sizeof(int*)); 

E qui è l'esempio in C++ che non funziona (non ghisa):

int *int_ptr = malloc(sizeof(int*)); 

Ho sentito che in C, infatti, trasmettere un'uscita da malloc() è un errore.

Qualcuno può commentare questo argomento?

+0

C++ essendo più sensibile al tipo richiede di specificare il tipo esatto tramite un cast. – Abhay

+9

Questo non è direttamente correlato alla tua domanda, ma penso che tu voglia 'sizeof (int)', non 'sizeof (int *)'. Detto questo, è ancora meglio usare 'sizeof * int_ptr', che garantisce che verrà assegnata la giusta quantità di memoria per qualsiasi tipo di puntamento a" int_ptr ". – bcat

+5

Perché dovresti usare malloc in C++? – SoapBox

risposta

27

diversi punti:

C permette puntatori void siano implicitamente convertiti in qualsiasi altro tipo di puntatore oggetto. Il C++ no.

Lanciare il risultato di malloc() in C interromperà una diagnostica utile se si dimentica di includere stdlib.h o altrimenti non si dispone di una dichiarazione per malloc() in ambito. Ricorda che se C vede una chiamata di funzione senza una dichiarazione precedente, assumerà che la funzione restituisca int. Se non si dispone di una dichiarazione per malloc() e si omette il cast, si otterrà una diagnostica per l'effetto che si sta tentando di assegnare tipi incompatibili (int al puntatore). Se si esegue il cast del risultato, si sopprime la diagnostica e potenzialmente ci sono problemi di runtime, poiché non è garantito che la conversione di un valore del puntatore in un int e di nuovo in un puntatore di nuovo fornirà un risultato utile.

Se stai scrivendo C++, dovresti utilizzare new e delete anziché malloc() e free().Sì, sì, sì, ho sentito tutti i motivi per cui le persone vogliono che il loro codice venga compilato come C e C++, ma i vantaggi dell'utilizzo del giusto strumento di gestione della memoria per la lingua superano i costi di mantenimento di due versioni IMO.

Nota: il tipo void * è stato aggiunto nello standard C89; le versioni precedenti di C avevano malloc() restituiscono char *, quindi in quelle versioni il cast era obbligatorio se si assegnava il risultato a un tipo di puntatore diverso. Quasi tutti supportano almeno lo standard C89, quindi le probabilità che tu entri in una di quelle vecchie implementazioni sono molto, molto basse.

+4

Nessun compilatore moderno emetterà un avviso per una dichiarazione mancante di malloc(), indipendentemente dai problemi di trasmissione? –

+0

@Daniel: Ciò dipende anche dal livello di avviso. L'avviso di trasmissione di solito si presenta con un livello di avviso inferiore rispetto alla dichiarazione mancante. –

+0

Forse, ma è comunque meglio lasciare il cast comunque. –

7

C supporta il cast implicito da void* in altri tipi di puntatori. C++ non lo consente.

Uno dei motivi che è visto di buon occhio in C per lanciare in modo esplicito il valore di ritorno di malloc è che se la firma malloc non è incluso nel unità di compilazione corrente, il compilatore assume che il tipo di ritorno è int e la conversione implicita di esso al tipo di puntatore che stai assegnando ai risultati in un avviso in fase di compilazione che avresti risolto immediatamente. Con un cast esplicito, se commetti questo errore, non verrà emesso alcun avviso.

13

Questo perché il C++ è un linguaggio fortemente tipizzato. In C++, i cast impliciti sono consentiti solo se si "allargano", cioè se il nuovo tipo può contenere tutti i valori che il vecchio tipo può contenere. È consentita la trasmissione da un tipo intero più piccolo a un tipo intero più grande; la trasmissione da qualsiasi tipo di puntatore a void* è consentita; è consentita la trasmissione da una sottoclasse alla sua superclasse. Tutti gli altri cast devono essere esplicitati, dicendo al compilatore "So cosa sto facendo, questo non è un errore".

malloc() restituisce un void*, che potrebbe essere qualsiasi cosa, quindi il compilatore non può garantire che il cast avrà successo (o essere significativo). Usando un cast esplicito, stai dicendo al compilatore che ciò che stai facendo è in realtà intenzionale.

C, OTOH, non ha regole di fusione così rigide; puoi tranquillamente scegliere tra due tipi diversi, e tu come programmatore sei responsabile di assicurarti che non succedano cose brutte come conseguenza.

+6

Posso lanciare implicitamente un 'int' a' bool' senza problemi. – UncleBens

+0

* "Questo perché il C++ è un linguaggio fortemente tipizzato." * ... e C non lo è !? – cdhowie

Problemi correlati