Assigning a dereference to a dereference

The article I was reading at http://www.cplusplus.com/doc/tutorial/pointers/ confused me when I found the following snippet of code around half way into the article.

1
2
3
*p = *q;
++p;
++q;

The question here is: How can a value (*p) be assigned another value (*q)? To test weather such an expression fails, I went ahead and wrote the following simple code and compiled it. I was surprised it didn't fail to do so.
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

int main() {
    int a = 10;
    int b = 2;
    int* pa = &a;
    int* pb = &b;

    *pa = *pb; // 10 = 2;

    return 0;
}

According to the article I linked, *pa = *pb; must mean 10 = 2;. I need help to understand what is going on.

Thank you.
Last edited on
*pa is not just a value. It's a reference to the actual object pointed to by pa.

When you assign to a reference, you're assigning to the real object.

It's essentially doing:
1
2
int& my_ref = *pa;
my_ref = *pb;
Last edited on
It's the same as if you'd written a = b;. That doesn't mean 10 = 2;, does it? It means "copy the value stored in b into a".
Likewise, *pa = *pb; means "copy the value stored at memory address pb into memory address pa".

Simply put, the language understands that values should be treated differently depending on which side of an assignment operator they are.
Last edited on
Hellp Xenophobe,

Line 9 is setting the value of the de-referenced value "pa" to the de-referenced value of "pb".

This may help:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

int main()
{
    int a = 10;
    int b = 2;
    
    int* pa = &a;
    int* pb = &b;

    std::cout<< "\npa = " << pa << "  pb = " << pb << '\n';
    
    std::cout<< "\n*pa = "<<*pa<<"  *pb = " << *pb << '\n';
    
    *pa = *pb; // 10 = 2;

    std::cout<< "\n*pa = "<<*pa<<"  *pb = " << *pb << '\n';
    
    return 0;
}

Click on the gear icon to run the program.

Andy
Part of the problem understanding things like this is terminology. Let’s see if we can clear it up.


A value is our data. We can name it (with a variable name).

 
  int x = -7;

Here we have an object-value — one that is its own entity stored somewhere in memory that we can access uniquely and modify. It currently represents the integer state “-7”.

The name we have given this unique object-value is “x”.


We can create an alias — another name — for this value:

 
  int& y = x;

Now I have two names I can use to access/modify the object-value: “x” and “y”.

The technical term for this alias is a reference.


Before direct references like that were encoded into the C++ language, waaaay back in C, we could create indirect references, which we call pointers.

That is, a pointer can be used to obtain a reference to an object-value.

 
  int* px;  // I am a pointer. 

A pointer is not itself a reference, or alias — it is its own value. In most cases a pointer is simply the index into a program’s memory of an object-value, which you can obtain with the “address of” operator:

 
  int* px = &x;  // I am a pointer with value = address in memory of x’s object-value 

All this memory addressing stuff is actually irrelevant, though. What is important is that a pointer can be used to obtain a direct reference:

 
  printf( "an integer value = %d\n", *px );

That is, the expression “*px” resolves to a direct reference to the object-value we named “x”.


So in your example you have two value-objects, named “a” and “b” respectively. Easy enough.

Then you create two pointers to them. Still good.

Then you “dereference” those pointers to obtain direct aliases for the two object-values and perform an assignment.

 
  *pa = *pb; // a = b;    NOT 10 = 2;    *pa ≡ a    and    *pb ≡ b 


What is neat about pointers is that you can obtain a reference to things that previously did not have a name.

1
2
3
  int* xs = new int[ 10 ];  // xs is a pointer to an array of unnamed int-values
  *xs = 42;                 // obtain a reference to the first int-value and assign it a value of ‘42’
  *(xs + 1) = 5;           // obtain a reference to the second int-value, etc. 

In C and C++, you can use a fancy syntactic sugar with the [] operator:

1
2
3
  int* xs = new int[ 10 ];
  xs[ 0 ] = 42;
  xs[ 1 ] = 5;

(Don’t forget to delete[] stuff you get with new[].)

Hope this helps.
@Ganado, so you're saying that dereferencing a pointer returns a reference and not the value being pointed to by the pointer? @Handy Andy's code example seems to be implying the same concept too.
A pointer is another name for an address.

Pointer = Address.

When you "dereference" an address (that is to say, dereference a pointer), you basically go to that memory location specified by the address. Whether you receive a reference to it or copy it depends on how you access it. For example:
1
2
3
4
5
6
7
char* dynamic = new char;
char temp = *dynamic; //Temp now holds a COPY of the data pointed by dynamic.
char& temp2 = *dynamic; // Temp2 now holds a REFERENCE to the data pointer by dynamic.

temp = 'a'; //Only temp is changed
temp2 = 'b'; //Both temp2 and *dynamic are changed.


Now, when you do *pa, you are directly accessing that value, so it is essentially a reference. Thus, when you set it equal to something else, the value it holds is changed.
Last edited on
@Ganado, so you're saying that dereferencing a pointer returns a reference and not the value being pointed to by the pointer?

That is exactly correct.

You dereference a pointer to obtain a reference to some object-value, by which the object-value may be accessed or modified.

That is no different than using an explicit name:

1
2
  int x;
  x = 5;  // I can use the name/reference/identifier/whatever “x” to modify the integer value 

* this is a little inexact, but close enough to follow without derailing further into arcane technical detail

Dereferencing pointers give you a reference which you have not named in code:
 
  *px = 94;  // dereference px to obtain a reference which is used to modify the integer 


The term “dereference” is to un-reference — which is to say, to convert the indirect reference into a direct reference.

Everything is accessed via a reference. Having a reference is the same as having direct access to an object-value, such as the int or char exampled in this discussion.
Wow! Many thanks ya'll. Especially @Duthomhas. It can't be more clear than this. Thank you very much.
Topic archived. No new replies allowed.