hi there, I'm coding in windows, c++, but when I traslate my code to ubuntu, g++, I get this error: lvalue required as left operand of assigment
This is the line where I get the error:

&*raiz=&*p;

What could be the problem?
*raiz and *p are pointers to an avl structure:

typedef struct nodo{
    int dato;
    int fe;
    int color;
    struct nodo *izq;
    struct nodo *der;
    struct nodo *padre;
}nodo;
typedef struct nodo *avl;

and this is the method where I have the problem:

void RSD(avl *raiz){  
    avl *p;  p=new avl;  *p=NULL;
    avl *q;  q=new avl;  *q=NULL;
    avl *a;  a=new avl;  *a=NULL;

    *a = (nodo*)*raiz;        
    *p = (*a)->izq;  
    *q = (*p)->der;

    (*a)->izq=*q;
    (*q)->padre=*a;
    (*a)->padre=*p;

    if ((*raiz)->padre->dato!=(*raiz)->dato)
        (*p)->padre=(*raiz)->padre;
    else
        (*p)->padre=*p; 

    &*raiz=&*p;  //ERROR!!
    *p=(*raiz)->der;
     *q=(*p)->izq;

}

Could someone tell me why I am having this error please? :'(
thanks

Recommended Answers

All 11 Replies

How about explaining what you expect the statement to do? It looks like nonsense to me.

&*raiz means "give me the address of the contents of the thing the pointer raiz is pointing to"; '&' is an operator. It's a bit silly, as by definition raiz itself equals the address of the thing it is pointing to.

Saying "give me the address of the contents of the thing the pointer raiz is pointing to, and make it equal to this other thing here on the right" is a nonsense.

What are you trying to do with these two pointers, raiz and p?

&*raiz means "give me the address of the contents of the thing the pointer raiz is pointing to"; '&' is an operator. It's a bit silly, as by definition raiz itself equals the address of the thing it is pointing to.

Actually, &*raiz by itself would make sense if raiz were, say, an iterator rather than a pointer. What doesn't make sense is to try to assign a value to &*raiz -- unless *raiz has a type with unary operator& defined. Such types are best avoided in any event.

I defer entirely to The Koenig :)

Ok, so lets see if we can break-up this statement into pieces (which is NOT equivalent to &*raiz, but it illustrates a point):

nodo** raiz; //from your code, this is basically the type of raiz
  nodo*& tmp = *raiz; //when you dereference raiz, this is what happens
  nodo** ptmp = &tmp; //when you reference tmp again, this is what happens
  ptmp = &*p; //when you assign, this is what happens

The above works fine because ptmp is an lvalue (it is a variable with an identifier and thus, it can be assigned to). But, when you use &*raiz, you don't create an lvalue, you just create a temporary value which contains the address of *raiz, this is not an lvalue, it is called an rvalue (can only go on the right-side of an assignment).

This is why people here have said it makes no sense to do the statement you posted. You are basically creating a temporary variable and assigning a value to it. In any case, if the compiler allows it (and it should not!), the statement has no effect at all.

I'm guessing, what you really meant to do was simply raiz = p; . But, if your code works as is under Windows, then I guess you should just delete that statement since it has no effect.

PS: Whenever something compiles in "under Windows" (which I guess means with MSVC, the microsoft compiler) and fails to compile with GCC, there is probably a 99% chance that GCC is right. Microsoft compilers are notorious for having little bugs everywhere that allow very weird, non-sense statements to compile (at least for pre-2008 or 2005 versions).

The above works fine because ptmp is an lvalue (it is a variable with an identifier and thus, it can be assigned to). But, when you use &*raiz, you don't create an lvalue, you just create a temporary value which contains the address of *raiz, this is not an lvalue, it is called an rvalue (can only go on the right-side of an assignment).

well, what I´m trying to do is to save the pointer of the root of my avl tree(*raiz) and then make all the modifications, and save the resulting tree in *raiz.

I'm new in programming, but I think I understand your explanation, I can just write:

raiz=p;

and it will have the same effect as &*raiz=&*p;
I need to clear all this concepts with pointers, but you all help me a lot!

One big red flag that I see in all your explanations is that you always stick the * next to the name of the pointer. This hints at a classic misunderstanding beginners have with pointers. Notice how I always stuck the * next to the type in the declarations, not next to the variable name (it makes no difference in compilation, but it makes a difference when it comes to understanding it right). Understand this:

int* ptr; //this declares a variable called 'ptr' which stores a pointer (i.e. the address) to an integer (not allocated here).

When you are not in a declaration, if you put the * next to the pointer's name, it will dereference the pointer, meaning it will fetch the value at the address stored in the pointer variable.

When you have a variable, and apply the & operator on it, it takes the address of the variable. The address of a variable is just a value, a temporary value, it is not a pointer variable, and it is certainly not the pointer variable from which the original variable was obtained by dereferencing with *. When you have something that is a value, but is not a variable, in C++ lingo, it is called an rvalue (because it is not a variable, you cannot store values in it, but since it is a value, you can assign that value to a variable, i.e. it can appear on the right-hand-side of an assignment).

>>and it will have the same effect as &*raiz=&*p;
No. As I said, that statement should not compile, has no sensible meaning, probably does nothing if it happens to compile on your crappy windows compiler, but it really is unknown what the effect of that statement is. So, no raiz = p; does not have the same effect as &*raiz = &*p; , because the latter has an unknown effect if any.

>>well, what I´m trying to do is to save the pointer of the root of my avl tree(*raiz) and then make all the modifications, and save the resulting tree in *raiz.

Then it would appear that the statement you are looking for is:

*raiz = *p;

But, to be sure, you should explain how this function is called, how is the parameter passed on the call-site, and what you expect will happen to the parameter after the function is finished. It looks to me like you might find that pass-by-reference is what you need.

commented: good posts in this thread +16

no, I need to pass it by value.

I have this funcion, which is the insert function for an avl tree. It calls Comprobar_equilibrio(), wich tells me what rotations I have to do, and makes all the changes to the pointer to my structure (*r), but when I go out from Comprobar_equilibrio(), *r doesn´t changes.
//I don't want to paste the entirely code of the function, but this is what I have:

void insertar(avl *r, int dato){
// ......
Comprobar_equilibrio(&(*r)->padre);
}
(nodo*) Comprobar_equilibrio(avl *r){
//.....
fe(r);
//I send *r to other functions which returns me *r modified
return *r;
}

All this works perfectly, but on the moment I go out of Comprobar_equilibrio(), *r is still the same. I don't understand this very well, because when I call another functions in Comprobar_equilibrio(), the pointer do changes. why?

>>no, I need to pass it by value.

You are passing it by pointer, not by value. Passing-by-pointer is just a (bad) way of doing passing-by-reference. Here is a simple piece of code that illustrates the three methods:

#include <iostream>

void pass_by_value(int val) {
  val = 42;    //val is a local variable now, so modifying it will not modify the caller's variable.
};

void pass_by_reference(int& val) {
  val = 42;     //val is an alias for the caller's variable, so it can be modified.
};

void pass_by_pointer(int* val) {
  *val = 42;    //val points to the caller's variable, so it can be modified, after dereferencing the pointer 'val'.
};

int main() {
  int i = 0;
  pass_by_value(i);
  std::cout << "Passed-by-value yields i = " << i << std::endl;
  int j = 0;
  pass_by_reference(j);
  std::cout << "Passed-by-ref yields j = " << j << std::endl;
  int k = 0;
  pass_by_pointer(&k); //take the address of k.
  std::cout << "Passed-by-ptr yields k = " << k << std::endl;

  return 0;
};

In the above, the type int is used for the passed parameter. In your case, the type of the passed parameter is 'avl' (pointer to nodo). Make sure you understand what is going on in the above example, it will surely help you understand what you are doing, or trying to do.


>>All this works perfectly, but on the moment I go out of Comprobar_equilibrio(), *r is still the same.

Then, all is NOT working perfectly. I wonder what your definition of 'perfectly' is...


>>I don't understand this very well, because when I call another functions in Comprobar_equilibrio(), the pointer do changes. why?

When you pass a variable by a pointer to it, you can modify the original (caller's) variable by dereferencing that pointer. Just like in the example above, the fact that the caller's variable is also a pointer does not make any difference.

If you modify the actual pointer, without dereferencing it, that modification will not affect the caller's variable. In other words:

void no_modificar(avl* r) {
  r = NULL;
};

void no_modificar_o_falta(avl* r) {
  &*r = NULL;
};

void modificar(avl* r) {
  *r = NULL;
};

Thanks for the explanation, it helped me a lot!

This error is basically due to wrong use of the assignment operator.

Try using only 1 value on left hand side and computable value on right hand side.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.