2009-11-15 6 views
13

J'essaie de comprendre les différences entre C et C++ en ce qui concerne les pointeurs de vide. les compiles suivants en C mais pas C++ (toutes les compilations faites avec -ansi -pedantic -Wall gcc/g ++):pointeurs de vide: différence entre C et C++

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

Because malloc retours void*, C++ qui ne permet pas d'attribuer à int* en C ne permet cette.

Cependant, ici:

void foo(void* vptr) 
{ 
} 

int main() 
{ 
    int* p = (int*) malloc(sizeof(int)); 
    foo(p); 
    return 0; 
} 

Les deux C++ et C Compile avec ne se plaint. Pourquoi?

K & R2 dire:

Tout pointeur sur un objet peut être convertie en type void * sans perte d'information. Si le résultat est reconverti au type de pointeur d'origine , le pointeur d'origine est récupéré.

Et ce résume assez tout ce qu'il ya environ void* conversions en C++ C Qu'est-ce diktat norme?

+0

GMan explique correctement pourquoi vous obtenez l'erreur. Cela dit, si vous écrivez du code C++, vous devriez utiliser new/new [] et delete/delete [] au lieu de malloc/calloc et free/free. –

Répondre

31

En C, les conversions de pointeur vers et à partir de void* étaient toujours implicites.

En C++, les conversions de T* à void* sont implicites, mais void* nécessite une conversion.

+1

pouvez-vous donner une source pour votre 2ème déclaration? est-il écrit en standard C++? – zaharpopov

+6

Il n'y a pas grand-chose à citer, vraiment. C'est à la section 4.10.2.Il dit à peu près qu'un 'T *' peut être converti en un 'void *'. Il laisse de côté le contraire, ce qui implique que vous devez utiliser une distribution. – GManNickG

+0

@zaharpopov: recherche reinterpret_cast <> ou static_cast <> –

6

C++ est plus fortement typé que C. De nombreuses conversions, en particulier celles qui impliquent une interprétation différente de la valeur, nécessitent une conversion explicite. L'opérateur nouvel en C++ est un moyen sûr d'allouer la mémoire sur heap, sans une distribution explicite.

0

Il est utile de comprendre que les conversions de type pointeur ne nécessitent pas vraiment l'exécution d'instructions CPU supplémentaires. Ils sont analysés pendant la compilation pour comprendre les intentions du développeur. void * est un pointeur opaque. Tout cela dit que le type d'objet pointé est inconnu. C est faiblement typé. Il permet la conversion directe entre (void *) et tout (T*) implicitement. C++ est fortement typé. Une conversion de (void *) vers (T*) ne ferait pas vraiment de cas pour une langue fortement typée. Mais C++ devait rester rétrocompatible avec C, donc il devait permettre de telles conversions. Le principe directeur est alors: explicite est meilleur qu'implicite. Par conséquent, si vous souhaitez convertir un pointeur (void*) en un pointeur spécifique (T*), vous devez l'écrire explicitement dans le code. La conversion de (T*) en (void*) ne nécessite pas de conversion explicite, car il n'y a rien de plus pratique sur un pointeur (void *) directement (on peut cependant appeler free()). Par conséquent (T*) à la conversion (void*) est à peu près sûr.

+1

La question de savoir si les conversions de pointeurs nécessitent ou non des instructions de CPU est un détail d'implémentation. Il n'y a absolument rien dans les langages C et C++ qui nécessiterait que ces conversions soient purement conceptuelles (c'est-à-dire ne nécessitent pas d'instructions de la CPU). Au contraire, les deux langages sont spécifiquement formulés pour permettre des représentations différentes pour différents types de pointeurs. Bien que "comprendre" que dans un cas typique la conversion ne fasse vraiment rien au niveau de la CPU puisse effectivement être utile, l'écriture de code C ou C++ qui repose sur cette supposition est une erreur sérieuse. – AnT

+1

... Et je ne comprends pas le point sur "rester compatible arrière". C++ requiert une distribution explicite pour convertir 'void *'. C'est déjà * pas * rétrocompatible avec C. – AnT

+0

C++ n'est pas complètement rétrocompatible avec C. Il fournit juste des moyens de rendre la migration aussi facile que possible partout où cela est nécessaire. Passer d'être typé faiblement à fortement typé entraîne naturellement des problèmes de compatibilité. C++ essaye juste de fournir des moyens simples (comme faire un type de cast explicite sur un pointeur vide) pour faciliter la migration. –

Questions connexes