views:

392

answers:

7

Hello everyone,

Anything wrong with my code below? I got the compile error!

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;
}

Thanks in advance, George

+14  A: 

When you cast the BYTE* to char* a unnamed temporary entity is created with the type char*. The function you call takes a reference to a char* but you can't take a reference to such a temporary entity because it is not a real variable.

shoosh
Could you show me how you fix it?
George2
I'm not sure about that... it's a pointer, you are just telling the compiler to trust you... I'm pretty sure there's no temporary involved here.
UncleZeiv
fixing it depends on what you want to do and the reason why that function takes a reference to a pointer. @UncleZeiv - There is no spoon.
shoosh
"not a real value" - I think you mean not an l-value. Correct answer though. +1
Assaf Lavie
I have voted this up for its correctness and codelogic's for its solution. Merging both would make a correct and complete answer.
David Rodríguez - dribeas
+1  A: 

You are trying to pass a variable reference, but there is no such variable of type char* you could refer to.

It should work this way if I remember correctly:

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

Maybe it would be easier to just pass a value instead of a reference.

Dennis Kempin
It works, but why temporary variable does not work?
George2
Because you want to pass a reference. And you cannot reference to a variable that does not exist. So you need to create one. But I think that reference passing is not needed here. Why not just pass a value? void foo(char* p)
Dennis Kempin
It might not work as expected: if the function changes the received pointer, changes will be made to the ptr var and not to the original buffer.
David Rodríguez - dribeas
+1  A: 

Firstly, when you say

(char)buffer

You are lying to the compiler - buffer is pointer, not a char.

Secondly, even if the cast worked, it would produce a temporary, which cannot be bound to a non-const reference.

So, yes, there are at least two things wrong with your code.

anon
That's not what he said, he is casting to a char*.
flodin
His post has been edited
anon
+1  A: 

Write it like this:

int main() { 
  BYTE * buffer; 
  char* pbuf = (char*)buffer;
  foo(pbuf);
}
Hans Passant
If f() changes the received pointer, the change will apply to pbuf and not buffer.
David Rodríguez - dribeas
+4  A: 

The parameter of foo is a reference-to-a-pointer. buffer is a BYTE pointer. Reference require an exact match, assignment-compatible won't do.

Two solutions:

1) you probably don't need the '&' in front of p. Loose it and the code will compile.

2) Use a correctly typed variable so the reference will work:

 BYTE * buffer;
 char * b = (char *) buffer;
 foo (b);
 buffer = (BYTE*) b;  // because foo may change b
Henk Holterman
Assuming that a side-effect of foo is to modify the passed-in parameter, you'd better also do "buffer = (BYTE*)b;" after calling foo.
ChrisW
@ChrisW: you are right, I Will edit it in. Makes the ref issue cleare too.
Henk Holterman
+7  A: 

You can perform a reinterpret_cast<char*&> instead of a static cast

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

Or, you can make the argument a const reference:

void foo(char* const & p)
{
    return;
}
codelogic
+2  A: 

The buffer pointer is an "lvalue", but when the cast operation is applied to it, the expression:

(char*) buffer

is an "rvalue" (actually a "modifiable rvalue" - but I think that only matters in the upcoming C++0x). Non-const references cannot be bound to rvalues.

However, const references can be bound to rvalues. So the following modification to your program will compile:

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

Stephan T. Lavavej recently posted a blog entry that has great information about lvalues, rvalues, and references:

The article is actually about the new "rvalue references" that are coming in C++0x, but it has a great explanation of what lvalues and rvalues are and how they can and cannot work with references in C++98. It's a long read, but very much well worth it.

Michael Burr