Domanda

In questa domanda, qualcuno ha suggerito in un commento che dovrei non cast il risultato di malloc, cioè

int *sieve = malloc(sizeof(int) * length);

piuttosto che:

int *sieve = (int *) malloc(sizeof(int) * length);

Perché questo sarebbe il caso?

È stato utile?

Soluzione

No ; tu non lanci il risultato, poiché:

  • Non è necessario, poiché void * viene promosso automaticamente e in modo sicuro a qualsiasi altro tipo di puntatore in questo caso.
  • Aggiunge confusione al codice, i cast non sono molto facili da leggere (specialmente se il tipo di puntatore è lungo).
  • Ti fa ripetere, il che è generalmente negativo.
  • Può nascondere un errore se hai dimenticato di includere <stdlib.h>. Ciò può causare arresti anomali (o, peggio, non causare un arresto fino a molto tempo dopo in una parte completamente diversa del codice). Considera cosa succede se puntatori e numeri interi hanno dimensioni diverse; allora stai nascondendo un avviso lanciando e potresti perdere bit del tuo indirizzo di ritorno. Nota: a partire da C11 le funzioni implicite sono passate da C e questo punto non è più rilevante poiché non si presume automaticamente che le funzioni non dichiarate restituiscano int.

Come chiarimento, nota che ho detto " non lanci " ;, non " non ti serve per lanciare " ;. Secondo me, non è possibile includere il cast, anche se hai capito bene. Semplicemente non ci sono benefici nel farlo, ma un sacco di potenziali rischi, e incluso il cast indica che non si conoscono i rischi.

Si noti inoltre, come sottolineano i commentatori, che quanto sopra parla di C dritto, non di C ++. Credo fermamente in C e C ++ come lingue separate.

Per aggiungere ulteriori informazioni, il codice ripete inutilmente le informazioni sul tipo (length) che possono causare errori. È meglio determinare il puntatore utilizzato per memorizzare il valore restituito, su & Quot; lock & Quot; i due insieme:

int *sieve = malloc(length * sizeof *sieve);

Questo sposta anche sizeof in primo piano per una maggiore visibilità e fa cadere le parentesi ridondanti con size_t; sono necessari solo quando l'argomento è un nome di tipo. Molte persone sembrano non saperlo (o ignorarlo), il che rende il loro codice più dettagliato. Ricorda: malloc(sizeof *sieve * length * width) non è una funzione! :)


Mentre si sposta malloc(length * width * sizeof *sieve) in primo piano può aumentare la visibilità in alcuni rari casi, si dovrebbe anche prestare attenzione al fatto che, nel caso generale, dovrebbe essere meglio scrivere l'espressione come:

int *sieve = malloc(sizeof *sieve * length);

Dato che mantenere il length * width per primo, in questo caso, si assicura che la moltiplicazione venga eseguita con almeno width matematica.

Confronto: <=> rispetto a <=> il secondo potrebbe traboccare <=> quando <=> e <=> sono tipi più piccoli di <=>.

Altri suggerimenti

In C, non è necessario eseguire il cast del valore restituito malloc. Il puntatore a vuoto restituito da sieve viene convertito automagicamente nel tipo corretto. Tuttavia, se si desidera che il codice venga compilato con un compilatore C ++, è necessario un cast. Un'alternativa preferita nella comunità è usare quanto segue:

int *sieve = malloc(sizeof *sieve * length);

che inoltre ti libera dal doverti preoccupare di cambiare il lato destro dell'espressione se cambi il tipo di <=>.

I cast sono cattivi, come sottolineato dalla gente. Calcolatori appositamente puntatore.

esegui il cast, perché:

  • Rende il tuo codice più portatile tra C e C ++ e, come dimostra l'esperienza SO, molti programmatori affermano di scrivere in C quando scrivono davvero in C ++ (o C più compilatore locale estensioni).
  • In caso contrario può nascondere un errore : annotare tutti gli esempi SO di confusione su quando scrivere type * rispetto a type **.
  • L'idea che ti impedisce di notare che non sei riuscito a #include un file di intestazione appropriato manca la foresta per gli alberi . È come dire & Quot; non preoccuparti del fatto che non hai chiesto al compilatore di lamentarsi di non aver visto i prototipi - che fastidioso stdlib.h è la cosa REALE importante da ricordare! & Quot;
  • Forza un controllo incrociato cognitivo extra . Mette il (presunto) tipo desiderato proprio accanto all'aritmetica che stai facendo per la dimensione grezza di quella variabile. Scommetto che potresti fare uno studio SO che mostra che malloc() i bug vengono catturati molto più velocemente quando c'è un cast. Come per le asserzioni, le annotazioni che rivelano l'intento riducono i bug.
  • Ripetersi in un modo che la macchina può controllare è spesso un'idea eccezionale . In effetti, ecco cos'è un'asserzione, e questo uso del cast è un'asserzione. Le asserzioni sono ancora la tecnica più generale che abbiamo per ottenere il codice corretto, dal momento che Turing ha avuto l'idea così tanti anni fa.

Come altri hanno affermato, non è necessario per C, ma per C ++. Se pensi di compilare il tuo codice C con un compilatore C ++, per quali motivi, puoi invece utilizzare una macro, come:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

In questo modo puoi ancora scriverlo in un modo molto compatto:

int *sieve = NEW(int, 1);

e verrà compilato per C e C ++.

Dal Wikipedia :

  

Vantaggi del casting

     
      
  • Includere il cast può consentire a un programma o una funzione C di essere compilato come C ++.

  •   
  • Il cast consente versioni precedenti a 1989 di malloc che originariamente restituivano un carattere *.

  •   
  • Il casting può aiutare lo sviluppatore a identificare incoerenze nel dimensionamento del tipo nel caso in cui il tipo di puntatore di destinazione cambi, in particolare se il puntatore è dichiarato lontano dalla chiamata malloc () (sebbene i compilatori moderni e gli analizzatori statici possano avvisare di tale comportamento senza richiedere il cast).

  •   
     

Svantaggi del casting

     
      
  • Secondo lo standard ANSI C, il cast è ridondante.

  •   
  • L'aggiunta del cast potrebbe mascherare il mancato inserimento dell'intestazione stdlib.h , in   quale si trova il prototipo di malloc. In assenza di a   prototipo per malloc, lo standard richiede che il compilatore C.   supponiamo che malloc restituisca un int. Se non è presente alcun cast, viene visualizzato un avviso   emesso quando questo numero intero è assegnato al puntatore; tuttavia, con   il cast, questo avviso non viene prodotto, nascondendo un bug. Certo   architetture e modelli di dati (come LP64 su sistemi a 64 bit, dove   long e puntatori sono a 64 bit e int è a 32 bit), questo errore può   in realtà comporta un comportamento indefinito, come implicitamente dichiarato   malloc restituisce un valore a 32 bit mentre la funzione effettivamente definita   restituisce un valore a 64 bit. A seconda delle convenzioni di chiamata e della memoria   layout, ciò può provocare la distruzione dello stack. Questo problema è meno probabile   passare inosservati nei compilatori moderni, poiché producono uniformemente   avverte che è stata utilizzata una funzione non dichiarata, quindi un avvertimento lo farà   appaiono ancora. Ad esempio, il comportamento predefinito di GCC è mostrare a   avviso che legge " dichiarazione implicita incompatibile di built-in   & Funzione quot; indipendentemente dal fatto che il cast sia presente o meno.

  •   
  • Se il tipo di puntatore viene modificato nella sua dichiarazione, si può   inoltre, è necessario modificare tutte le linee in cui viene chiamato e lanciato malloc.

  •   

Anche se malloc senza casting è il metodo preferito e la maggior parte dei programmatori esperti lo sceglie , dovresti usare quello che ti piace conoscere i problemi.

vale a dire: se devi compilare il programma C come C ++ (anche se quelli sono un linguaggio separato) dovresti usare malloc con il casting.

In C puoi convertire implicitamente un puntatore vuoto in qualsiasi altro tipo di puntatore, quindi non è necessario un cast. L'uso di uno può suggerire all'osservatore casuale che c'è qualche motivo per cui uno è necessario, il che può essere fuorviante.

Non lanci il risultato di malloc, perché in questo modo aggiungi disordine inutile al tuo codice.

Il motivo più comune per cui le persone lanciano il risultato di malloc è perché non sono sicuri su come funzioni il linguaggio C. Questo è un segnale di avvertimento: se non sai come funziona un meccanismo linguistico particolare, non fai un'ipotesi. Cerca o chiedi su Stack Overflow.

Alcuni commenti:

  • Un puntatore vuoto può essere convertito in / da qualsiasi altro tipo di puntatore senza un cast esplicito (C11 6.3.2.3 e 6.5.16.1).

  • C ++ non consentirà tuttavia un cast implicito tra void* e un altro tipo di puntatore. Quindi in C ++, il cast sarebbe stato corretto. Ma se programmi in C ++, dovresti usare new e non malloc (). E non dovresti mai compilare il codice C usando un compilatore C ++.

    Se è necessario supportare sia C che C ++ con lo stesso codice sorgente, utilizzare le opzioni del compilatore per contrassegnare le differenze. Non tentare di soddisfare entrambi gli standard linguistici con lo stesso codice, perché non sono compatibili.

  • Se un compilatore C non riesce a trovare una funzione perché hai dimenticato di includere l'intestazione, otterrai un errore del compilatore / linker a riguardo. Quindi, se hai dimenticato di includere <stdlib.h> non è un problema, non sarai in grado di creare il tuo programma.

  • Su compilatori antichi che seguono una versione dello standard che ha più di 25 anni, dimenticare di includere int comporterebbe comportamenti pericolosi. Perché in quello standard antico, le funzioni senza prototipo visibile hanno implicitamente convertito il tipo restituito in <=>. Trasmettere esplicitamente il risultato da malloc nasconderebbe questo bug.

    Ma questo è davvero un problema. Non stai usando un computer di 25 anni, quindi perché dovresti usare un compilatore di 25 anni?

In C ottieni una conversione implicita da void* a qualsiasi altro puntatore (dati).

Il cast del valore restituito da malloc() non è necessario ora, ma vorrei aggiungere un punto che sembra che nessuno abbia sottolineato:

Nei tempi antichi, cioè prima che ANSI C fornisse void * come tipo generico di puntatori, char * è il tipo per tale utilizzo. In tal caso, il cast può chiudere gli avvisi del compilatore.

Riferimento: FAQ C

Non è obbligatorio eseguire il cast dei risultati di malloc, poiché restituisce void* e un <=> può essere indirizzato a qualsiasi tipo di dati.

Solo aggiungendo la mia esperienza, studiando ingegneria informatica vedo che i due o tre professori che ho visto scrivere in C lanciano sempre malloc, tuttavia quello che ho chiesto (con un immenso CV e comprensione di C) mi ha detto che è assolutamente inutile ma usato solo per essere assolutamente specifico e per far entrare gli studenti nella mentalità di essere assolutamente specifici. Fondamentalmente il casting non cambierà nulla nel modo in cui funziona, fa esattamente ciò che dice, alloca la memoria e il casting non ha effetto, ottieni la stessa memoria e anche se lo cast su qualcos'altro per errore (e in qualche modo elude il compilatore errori) C accederà allo stesso modo.

Modifica: il cast ha un certo punto. Quando si utilizza la notazione di array, il codice generato deve sapere quante posizioni di memoria deve avanzare per raggiungere l'inizio dell'elemento successivo, ciò si ottiene attraverso il cast. In questo modo sai che per un doppio vai avanti di 8 byte mentre per un int vai a 4, e così via. Pertanto, non ha alcun effetto se si utilizza la notazione del puntatore, nella notazione di matrice diventa necessario.

Questo è ciò che Il riferimento alla libreria C GNU il manuale dice:

  

È possibile memorizzare il risultato di malloc in qualsiasi variabile puntatore senza a   cast, perché ISO C converte automaticamente il tipo void * in un altro   tipo di puntatore quando necessario. Ma il cast è necessario in contesti   diversi dagli operatori di assegnazione o se si desidera eseguire il codice   in C. tradizionale

E in effetti lo standard ISO C11 (p347) dice così:

  

Il puntatore restituito se l'allocazione ha esito positivo è opportunamente allineato   che può essere assegnato a un puntatore a qualsiasi tipo di oggetto con a   requisito di allineamento fondamentale e quindi utilizzato per accedere a tale   oggetto o un array di tali oggetti nello spazio allocato (fino a quando   lo spazio è esplicitamente deallocato)

Un puntatore vuoto è un puntatore generico e C supporta la conversione implicita da un tipo di puntatore vuoto ad altri tipi, quindi non è necessario digitarlo esplicitamente.

Tuttavia, se si desidera che lo stesso codice funzioni perfettamente compatibile su una piattaforma C ++, che non supporta la conversione implicita, è necessario eseguire la tipografia, quindi tutto dipende dall'usabilità.

Il tipo restituito è nullo *, che può essere trasmesso al tipo di puntatore di dati desiderato per essere dichiarabile.

Nel linguaggio C, un puntatore vuoto può essere assegnato a qualsiasi puntatore, motivo per cui non dovresti usare un cast di tipo. Se vuoi & Quot; digita safe & Quot; allocazione, posso raccomandare le seguenti funzioni macro, che uso sempre nei miei progetti C:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

Con questi in atto puoi semplicemente dire

NEW_ARRAY(sieve, length);

Per le matrici non dinamiche, la terza macro di funzioni indispensabili è

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

che rende i loop di array più sicuri e più convenienti:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}

Dipende dal linguaggio di programmazione e dal compilatore. Se usi malloc in C non è necessario digitare cast, in quanto digiterà automaticamente cast, tuttavia se usi C ++ devi digitare cast perché void* restituirà un <=> tipo.

Le persone abituate a GCC e Clang sono viziate. Non è poi così bello là fuori.

Sono stato piuttosto inorridito nel corso degli anni dai compilatori incredibilmente vecchi che mi è stato richiesto di usare. Spesso aziende e manager adottano un approccio ultra-conservativo per cambiare compilatori e non testeranno nemmeno se un nuovo compilatore (con una migliore conformità agli standard e ottimizzazione del codice) funzionerà nel loro sistema. La realtà pratica per gli sviluppatori che lavorano è che quando stai programmando devi coprire le tue basi e, sfortunatamente, lanciare malloc è una buona abitudine se non puoi controllare quale compilatore può essere applicato al tuo codice.

Vorrei anche suggerire che molte organizzazioni applicano un proprio standard di codifica e che che dovrebbe essere il metodo che le persone seguono se definito. In assenza di una guida esplicita, tendo a cercare la maggior parte delle probabilità di compilare ovunque, piuttosto che una rigida aderenza a uno standard.

L'argomento secondo cui non è necessario secondo gli standard attuali è abbastanza valido. Ma tale argomento omette le funzionalità del mondo reale. Non codifichiamo in un mondo governato esclusivamente dallo standard del giorno, ma dalle praticità di ciò che mi piace chiamare & Quot; campo di realtà della gestione locale & Quot ;. E questo è piegato e contorto più di quanto lo sia mai stato lo spazio. : -)

YMMV.

Tendo a pensare a lanciare malloc come un'operazione difensiva. Non carino, non perfetto, ma generalmente sicuro. (Onestamente, se non hai incluso stdlib.h, hai via più problemi che lanciare malloc!).

Ho inserito il cast semplicemente per mostrare la disapprovazione del brutto buco nel sistema dei tipi, che consente a codice come il seguente frammento di compilare senza diagnostica, anche se non vengono utilizzati cast per determinare la conversione errata:

double d;
void *p = &d;
int *q = p;

Vorrei che non esistesse (e non esiste in C ++) e quindi lancio. Rappresenta il mio gusto e la mia politica di programmazione. Non sto solo lanciando un puntatore, ma in effetti, lancio una scheda e scagliando demoni di stupidità . Se non riesco in realtà scacciare la stupidità , almeno lasciami esprimere il desidero farlo con un gesto di protesta.

In effetti, una buona pratica è quella di racchiudere malloc (e gli amici) con funzioni che restituiscono unsigned char * e sostanzialmente di non usare mai void * nel tuo codice. Se hai bisogno di un generico puntatore a qualsiasi oggetto, usa char * o memset e disponi i cast in entrambe le direzioni. L'unico rilassamento che può essere concesso, forse, sta usando funzioni come memcpy e grep senza cast.

Per quanto riguarda il cast e la compatibilità con C ++, se scrivi il tuo codice in modo che venga compilato come C e C ++ (nel qual caso devi lanciare il valore di ritorno di strip_qual durante l'assegnazione in qualcosa diverso da const), puoi fare una cosa molto utile per te stesso: puoi usare le macro per il cast che si traducono in cast in stile C ++ durante la compilazione come C ++, ma riducono a un cast C durante la compilazione come C:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

Se aderisci a queste macro, una semplice volatile ricerca nella tua base di codice per questi identificatori ti mostrerà dove sono tutti i tuoi cast, in modo da poter verificare se qualcuno di essi è errato.

Quindi, andando avanti, se compili regolarmente il codice con C ++, imporrà l'uso di un cast appropriato. Ad esempio, se si utilizza -Wold-style-cast solo per rimuovere un (type) o <=>, ma il programma cambia in modo tale che ora è coinvolta una conversione di tipo, si otterrà una diagnostica e sarà necessario utilizzare un combinazione di cast per ottenere la conversione desiderata.

Per aiutarti ad aderire a queste macro, il compilatore GNU C ++ (non C!) ha una bella funzionalità: una diagnostica opzionale che viene prodotta per tutte le occorrenze di cast in stile C.

     -Wold-style-cast (C++ and Objective-C++ only)
         Warn if an old-style (C-style) cast to a non-void type is used
         within a C++ program.  The new-style casts (dynamic_cast,
         static_cast, reinterpret_cast, and const_cast) are less vulnerable
         to unintended effects and much easier to search for.

Se il tuo codice C viene compilato come C ++, puoi utilizzare questa opzione <=> per scoprire tutte le occorrenze della sintassi <=> che può insinuarsi nel codice e dare seguito a questi diagnostici sostituendolo con un appropriato scelta tra le macro sopra (o una combinazione, se necessario).

Questo trattamento delle conversioni è la più grande giustificazione tecnica autonoma per lavorare in un " Clean C " ;: il dialetto C e C ++ combinato, che a sua volta giustifica tecnicamente il casting del valore di ritorno di <= >.

La cosa migliore da fare quando si programma in C, quando ciò è possibile:

  1. Rendere il vostro programma di compilazione attraverso un compilatore C con tutte le avvertenze acceso -Wall e di correggere tutti gli errori e gli avvisi
  2. Assicurarsi che non vi siano le variabili dichiarate come auto
  3. Poi compilarlo con un compilatore C++ con -Wall e -std=c++11.Correggere tutti gli errori e gli avvisi.
  4. Ora compilate utilizzando il compilatore C di nuovo.Il vostro programma deve compilare ora, senza alcun preavviso, e contengono un minor numero di bug.

Questa procedura consente di usufruire di C++ controllo di tipo strict, riducendo così il numero di bug.In particolare, questa procedura impone di includere stdlib.ho si otterrà

malloc non è stato dichiarato all'interno di questo ambito

e anche le forze per lanciare il risultato di malloc o si otterrà

voci di conversione da void* per T*

o che cosa mai il vostro tipo di destinazione è.

Il solo benefici da scrivere in C invece che in C++ che posso trovare sono

  1. C è ben specificato ABI
  2. C++ potrebbe generare codice più [eccezioni, RTTI, modelli, runtime polimorfismo]

Da notare che il secondo contro dovrebbe, nel caso ideale scompaiono quando si utilizza il sottoinsieme comune di C insieme con il statico polimorfici funzione.

Per coloro che trova C++ rigide regole scomodo, si può utilizzare il C++11 funzione con tipo dedotto

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

No, non lanci il risultato di malloc().

In generale, non esegui il cast da o verso void * .

Un motivo tipico indicato per non farlo è che il mancato #include <stdlib.h> potrebbe passare inosservato. Questo non è più un problema da molto tempo poiché C99 ha reso illegali le dichiarazioni di funzioni implicite , quindi se il tuo compilatore è conforme almeno a C99, otterrai un messaggio diagnostico.

Ma c'è un motivo molto più forte di non introdurre lanci puntatori non necessari:

In C, un cast puntatore è quasi sempre un errore . Ciò è dovuto alla seguente regola ( & # 167; 6.5 p7 in N1570, l'ultima bozza per C11):

  

Un oggetto deve avere il suo valore memorizzato accessibile solo da un'espressione lvalue che ne ha una   i seguenti tipi:
  & # 8212; un tipo compatibile con il tipo effettivo dell'oggetto,
  & # 8212; una versione qualificata di un tipo compatibile con il tipo effettivo dell'oggetto,
  & # 8212; un tipo che è il tipo con o senza segno corrispondente al tipo effettivo di   oggetto,
  & # 8212; un tipo di tipo con o senza segno corrispondente a una versione qualificata di   tipo effettivo dell'oggetto,
  & # 8212; un tipo di aggregato o unione che include uno dei tipi di cui sopra tra i suoi   membri (incluso, ricorsivamente, un membro di un'unione separata o contenuta) o
  & # 8212; un tipo di carattere.

Questa è anche conosciuta come la regola di aliasing rigorosa . Quindi il codice seguente è comportamento indefinito :

long x = 5;
double *p = (double *)&x;
double y = *p;

E, a volte sorprendentemente, è anche il seguente:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

A volte, devi devi lanciare i puntatori, ma data la regola di aliasing rigorosa , devi stare molto attento. Pertanto, qualsiasi occorrenza di un cast di puntatori nel codice è un luogo in cui devi ricontrollare la sua validità . Pertanto, non si scrive mai un cast puntatore non necessario.

tl; dr

In poche parole: poiché in C, qualsiasi occorrenza di un puntatore lanciato dovrebbe sollevare una bandiera rossa per il codice che richiede un'attenzione speciale, non dovresti mai scrivere non necessario lancia il puntatore.


Note a margine:

  • Esistono casi in cui è necessario un cast su printf(), ad es. se si desidera stampare un puntatore:

    int x = 5;
    printf("%p\n", (void *)&x);
    

    Il cast è necessario qui, perché <=> è una funzione variadica, quindi le conversioni implicite non funzionano.

  • In C ++, la situazione è diversa. Il cast di tipi di puntatori è piuttosto comune (e corretto) quando si tratta di oggetti di classi derivate. Pertanto, ha senso che in C ++ la conversione da e verso <=> sia non implicita. C ++ ha un intero set di diversi tipi di casting.

Preferisco fare il cast, ma non manualmente. Il mio preferito è usare le macro g_new e g_new0 di glib. Se non si utilizza glib, aggiungerei macro simili. Queste macro riducono la duplicazione del codice senza compromettere la sicurezza del tipo. Se si sbaglia il tipo, si otterrebbe un cast implicito tra puntatori non nulli, che causerebbe un avviso (errore in C ++). Se si dimentica di includere l'intestazione che definisce malloc e calloc, si otterrebbe un errore. 0 e <=> accettano entrambi gli stessi argomenti, diversamente da <=> che accetta meno argomenti di <=>. Aggiungi <=> per ottenere memoria a zero inizializzazione. Il codice può essere compilato con un compilatore C ++ senza modifiche.

Il cast è solo per C ++ non C. Nel caso in cui si stia utilizzando un compilatore C ++, è meglio modificarlo in compilatore C.

Il concetto alla base del puntatore vuoto è che può essere trasmesso a qualsiasi tipo di dati, motivo per cui malloc restituisce vuoto. Inoltre, devi essere consapevole del typecasting automatico. Quindi non è obbligatorio lanciare il puntatore anche se è necessario farlo. Aiuta a mantenere pulito il codice e aiuta il debug

  1. Come altri hanno affermato, non è necessario per C, ma per C ++.

  2. Includere il cast può consentire a un programma o una funzione C di essere compilato come C ++.

  3. In C non è necessario, poiché void * viene promosso automaticamente e in modo sicuro verso qualsiasi altro tipo di puntatore.

  4. Ma se lo fai, puoi nascondere un errore se ti sei dimenticato di includere stdlib.h . Ciò può causare arresti anomali (o, peggio, non causare un arresto anomalo) fino a dopo in una parte completamente diversa del codice).

    Perché stdlib.h contiene il prototipo per malloc trovato. Nel assenza di un prototipo per malloc, lo standard richiede che il C il compilatore presuppone che malloc restituisca un int. Se non c'è cast, a l'avviso viene emesso quando questo numero intero viene assegnato al puntatore; tuttavia, con il cast, questo avviso non viene prodotto, nascondendo un bug.

Un puntatore vuoto è un puntatore generico e C supporta la conversione implicita da un tipo di puntatore vuoto ad altri tipi, quindi non è necessario digitarlo esplicitamente.

Tuttavia, se si desidera che lo stesso codice funzioni perfettamente compatibile su una piattaforma C ++, che non supporta la conversione implicita, è necessario eseguire la tipografia, quindi tutto dipende dall'usabilità.

Il casting di malloc non è necessario in C ma obbligatorio in C ++.

Il cast non è necessario in C a causa di:

  • void * viene promosso automaticamente e in modo sicuro a qualsiasi altro tipo di puntatore nel caso di C.
  • Può nascondere un errore se hai dimenticato di includere <stdlib.h>. Ciò può causare arresti anomali.
  • Se i puntatori e i numeri interi hanno dimensioni diverse, allora stai nascondendo un avviso lanciando e potresti perdere bit dell'indirizzo restituito.
  • Se il tipo di puntatore viene modificato durante la sua dichiarazione, potrebbe essere necessario modificare tutte le righe in cui malloc viene chiamato e trasmesso.

D'altra parte, il casting può aumentare la portabilità del programma. cioè, consente a un programma o una funzione C di essere compilato come C ++.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top