Question

En C, ce n'est pas une erreur de pointeurs de la distribution vers et à partir void *.

Un obstacle majeur dans le portage vers C ++ est la nécessité de pointeurs de la distribution lors du retour des fonctions traitant des pointeurs génériques tels que malloc, et les fonctions déclarées dans mon propre code tel que void *block_get(Blkno const blkno);.

Mon code est cependant destiné à être compilé par C et compilateurs C ++ avec succès. Si je donne des moulages explicites partout pour le bien de C ++, ils doivent être moulages de type C et I peuvent être des bugs de masquage en raison de la conversion des types non-pointeur vers et à partir des types de pointeurs des deux langues.

Mon erreur de référence est le suivant:

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

qui MSVC produit:

  

Erreur 2 Erreur C2440: 'initialisation': ne peut pas convertir les 'void *' à 'CPF *' e: \ src \ CPF \ cpfs.c 179

De toute évidence, je ne peux pas utiliser new ou static_cast que je serais naturellement utiliser si je n'utilisait plus C. Quelle est la meilleure façon d'assurer la sécurité maximale de type entourant void *for chaque langue avec verbosité minimale?

Était-ce utile?

La solution

Peut-être quelque chose comme ça? (Non testé, aucun compilateur disponible, ne pas utiliser des macros très souvent):

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

Autres conseils

Je vous suggère soit tout simplement en utilisant des moulages de style C, ou envelopper la distribution dans une macro qui soit remplacée par rien (en C), ou un static_cast en C ++.

Si le compilateur supporte decltype(), vous pouvez utiliser la magie macro pour éviter d'avoir à répéter explicitement le nom du type (et, grâce à sizeof, la taille de l'élément):

#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

Exemple d'utilisation:

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

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

La solution de nettoyage serait probablement juste utiliser un compilateur C et lier les fichiers objet, mais ...

faire une fonction allocateur de remplacement que vous pouvez définir différemment pour C et C ++ construit: - Quelque chose comme ça dans un fichier d'en-tête:

#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

Maintenant que vous avez, en c ++ builds, une fonction qui peut déduire le type de chose de son affaire, et en C construit, sa fonction régulière qui retourne un void *.

Le seul problème est la nécessité de passer le pointeur d'allouer - le compilateur c ++ essayer l'habitude de déduire un paramètre de modèle basé uniquement sur le type de retour d'une fonction afaik. Ainsi, vous pouvez l'appeler agnostically comme ceci: -

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

La seule solution que je sais est de faire explicitement casting:

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

Ici, les compilateurs sont satisfaits. Que vous souvenant que, pour les compilateurs anciens malloc peut retourner char *.

HTH

Mario

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top