Domanda

In C, non è un errore di puntatori del cast da e per void *.

Uno dei principali ostacoli nel porting di C ++ è la necessità di puntatori del cast al ritorno dalle funzioni che si occupano di puntatori generici come malloc e funzioni dichiarate nel mio codice, come void *block_get(Blkno const blkno);.

Il mio codice tuttavia è destinato ad essere compilato da C e compilatori C ++ con successo. Se fornisco cast espliciti in tutto il mondo per il gusto di C ++, devono essere calchi in stile C e I possono essere mascherare errori dovuti alla fusione tipi non-puntatore da e per tipi di puntatore da entrambe le lingue.

Il mio errore di riferimento è il seguente:

struct Cpfs *cpfs = calloc(1, sizeof(*cpfs));

che a sua MSVC produce:

  

Errore 2 Errore C2440: 'inizializzazione': non può convertire da '* vuoto' a 'CPF *' e: \ src \ CPF \ cpfs.c 179

Evidentemente non posso usare new o static_cast che userei naturalmente se non ho più stavo usando C. Qual è il modo migliore per garantire la massima sicurezza di tipo circostante void *for ogni lingua con il minimo livello di dettaglio?

È stato utile?

Soluzione

Forse qualcosa di simile? (Non testato, nessun compilatore a disposizione, non si utilizza le macro molto spesso):

#ifdef __cplusplus
    #define pointer_cast(type, pointer) reinterpret_cast<type>(pointer)
#else
    #define pointer_cast(type, pointer) (type)(pointer)
#endif

Altri suggerimenti

suggerirei sia semplicemente utilizzando C calchi di stile, o avvolgendo il cast in una macro che o si espande per niente (in C), o una static_cast in C ++.

Se il proprio compilatore decltype(), è possibile utilizzare alcune macro magia per evitare di dover ripetere in modo esplicito il nome del tipo (e, grazie alla sizeof, la dimensione dell'elemento):

#ifdef __cplusplus
#define my_calloc(VAR, COUNT) \
    static_cast<decltype(VAR)>(std::calloc(COUNT, sizeof *VAR))
#else
#define my_calloc(VAR, COUNT) calloc(COUNT, sizeof *VAR)
#endif

Esempio di utilizzo:

#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif

struct Cpfs *cpfs = my_calloc(cpfs, 42);

La soluzione più pulita sarebbe probabilmente utilizzare solo un compilatore C e collegare i file oggetto, anche se ...

fare una funzione di sostituzione allocatore che è possibile definire in modo diverso per C e C ++ costruisce: - Qualcosa di simile a un file di intestazione:

#ifdef __cplusplus
template<typename TypeT>
TypeT* MyAlloc(TypeT** pOut,size_t cb){
  *pOut = static_cast<TypeT*>(malloc(cb)); //aint c++ pretty.
  return *pOut;
}
#else
  extern void* MyAlloc(void** ppv, size_t cb);
#endif

Ora si deve, in C ++ costruisce, una funzione che può dedurre il tipo di cosa relativo trattare con, e in C costruisce, la sua una normale funzione che restituisce un * vuoto.

L'unico problema è la necessità di passare il puntatore di destinare - il compilatore C ++ solito cercare di dedurre un parametro di modello basato solo sul tipo di ritorno di una funzione afaik. Così si potrebbe chiamare agnosticamente in questo modo: -

int *p;
if(MyAlloc(&p,sizeof(int)*n)){
  ...

L'unica soluzione che conosco è quello di fare cast esplicito:

struct Cpfs *cpfs = (Cpfs*)calloc(1, sizeof(*cpfs));

Qui entrambi i compilatori sono soddisfatti. Inoltre che ricorda, che per i compilatori più anziani malloc può restituire char *.

hth

Mario

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