2009-02-15 8 views
3

Quelque chose ne va pas avec mon code ci-dessous? J'ai eu l'erreur de compilation!Strange char * erreur de compilation?

typedef unsigned char BYTE; 

void foo(char* & p) 
{ 
return; 
} 

int main() 
{ 
    BYTE * buffer; 
    // error C2664: 'foo' : cannot convert parameter 1 from 'char *' to 'char *&' 
    foo ((char*)buffer); 

    return 0; 
} 

Merci à l'avance, George

+0

Je pense que ChrisW a effectivement corrigé le bogue dans votre code lors de l'édition ... vous étiez en train de lancer un BYTE * en un (char) au lieu d'un (char *). – UncleZeiv

+0

Non, vous ne pouvez pas passer une référence temporaire par non-const, donc l'erreur est toujours là: la distribution crée un temporaire et qui ne peut pas être transmis par référence. –

+0

@UncleZeiv l'histoire d'édition dit que j'ai fait, mais je ne me souviens pas de le faire. Je ne peux pas l'expliquer. Cela aurait-il pu être quelqu'un d'autre, le PO même, en train de faire une édition simultanée? – ChrisW

Répondre

14

Lorsque vous lancez l'BYTE*-char* une entité temporaire sans nom est créée avec le type char*. La fonction que vous appelez prend une référence à char* mais vous ne pouvez pas prendre de référence à une telle entité temporaire car ce n'est pas une variable réelle.

+0

Pourriez-vous me montrer comment vous le réparer? – George2

+0

Je ne suis pas sûr de ça ... c'est un pointeur, vous dites juste au compilateur de vous faire confiance ... Je suis à peu près sûr qu'il n'y a pas de temporaire impliqué ici. – UncleZeiv

+0

La réparation dépend de ce que vous voulez faire et de la raison pour laquelle cette fonction prend une référence à un pointeur. @UncleZeiv - Il n'y a pas de cuillère. – shoosh

1

Vous essayez de transmettre une référence de variable, mais il n'y a pas de telle variable de type char * auquel vous pouvez vous référer.

Il devrait fonctionner de cette façon si je me souviens bien:

BYTE * buffer; 
char* ptr = (char*)buffer; 
foo(ptr); // now you have a matching variable to refer to. 

Peut-être qu'il serait plus facile de passer juste une valeur au lieu d'une référence.

+0

Cela fonctionne, mais pourquoi la variable temporaire ne fonctionne pas? – George2

+0

Parce que vous voulez passer une référence. Et vous ne pouvez pas faire référence à une variable qui n'existe pas. Donc vous devez en créer un. Mais je pense que le passage de référence n'est pas nécessaire ici. Pourquoi ne pas simplement passer une valeur? void foo (char * p) –

+0

Cela peut ne pas fonctionner comme prévu: si la fonction change le pointeur reçu, les modifications seront apportées à la commande ptr var et non au tampon d'origine. –

1

Tout d'abord, quand vous dites

(char)buffer 

Vous mentez au compilateur - tampon est pointeur, pas char. Deuxièmement, même si le cast travaillait, il produirait un temporaire, qui ne peut pas être lié à une référence non-const. Donc, oui, il y a au moins deux choses qui ne vont pas dans votre code.

+0

Ce n'est pas ce qu'il a dit, il lance un char *. – flodin

+0

Son message a été modifié –

1

écrire comme ceci:

int main() { 
    BYTE * buffer; 
    char* pbuf = (char*)buffer; 
    foo(pbuf); 
} 
+0

Si f() modifie le pointeur reçu, la modification s'appliquera à pbuf et pas au tampon. –

4

Le paramètre de foo est une référence à un pointeur. buffer est un pointeur BYTE. Référence nécessitent une correspondance exacte, l'attribution-compatible ne fera pas.

Deux solutions:

1) vous ne avez probablement pas besoin du '&' devant p. Desserrez-le et le code compilera.

2) Utiliser une variable typée correctement si la référence fonctionnera:

BYTE * buffer; 
char * b = (char *) buffer; 
foo (b); 
buffer = (BYTE*) b; // because foo may change b 
+0

En supposant qu'un effet secondaire de foo est de modifier le paramètre transmis, vous feriez mieux de faire aussi "buffer = (BYTE *) b;" après avoir appelé foo. – ChrisW

+0

@ChrisW: vous avez raison, je vais l'éditer. Rend le problème de ref aussi. –

7

Vous pouvez effectuer une reinterpret_cast<char*&> au lieu d'une distribution statique

foo (reinterpret_cast<char*&>(buffer)); 

Ou, vous pouvez faire valoir un const référence:

void foo(char* const & p) 
{ 
    return; 
} 
2

Le pointeur buffer est un "lvalue", bu t lorsque l'opération de coulée est appliquée, l'expression:

(char*) buffer 

est un « rvalue » (en fait une « rvalue modifiable » - mais je pense que seules les questions dans la prochaine C++ 0x). Les références non const ne peuvent pas être liées à des valeurs.

Cependant, const les références peuvent être liées à des valeurs.Ainsi, la modification suivante à votre programme compilera:

void foo(char* const& p) // added 'const' 

Stephan T. Lavavej a récemment publié une entrée de blog qui a d'excellentes informations sur lvalues, rvalues ​​et références:

L'article traite en réalité des nouvelles "références rvalue" qui arrivent en C++ 0x, mais il a une excellente explication de ce que lvalues ​​et rvalues ​​sont et comment elles peuvent et ne peuvent pas fonctionner avec des références en C++ 98. C'est une longue lecture, mais ça vaut vraiment le coup.