The difference between pointers and asterisk pointers?

We've been studying pointers the last few days, and I'm having difficulty understanding the differences between pointers with an asterisk and ones without. I know that pointers have something to do with the hex codes of memory on a computer, and that they're similar to the & sign in c++. What I don't understand is when to use the *ptr or the ptr itself. It seems like sometimes you can cout one and it'll give you the number, but then in another instance, it gives you a hex code. I've googled around for a bit, finding information on pointers on learncpp and the documentation section of this website, but I'm still struggling to understand when to use what thing and what exactly they do. Thanks in advance!
First thing's first: A pointer is simply an address in memory. That's all it is, by itself. It's a number.

Every time you declare a variable, that variable will have an address, and this address is where that variable is stored in memory. The compiler/runtime decides for you what this address will be.

1
2
3
4
5
6
int main()
{
    int a = 42; // declare a variable
    int* ptr; // declare a pointer-to-int. Note: we have not assigned it to anything
    ptr = &a; // the & operator here takes the address of a.
}


In the above example, we set ptr to be the address of a. In other words, we set ptr to point to a.

To repeat myself: ptr by itself is just the memory address of a.
But when you dereference ptr, you get the actual data at the address (pointer) you dereference.

You dereference a pointer using the * unary operator.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Example program
#include <iostream>
#include <string>

int main()
{
    int a = 42;
    int b = 7;
    
    int* ptr = &a;
    
    // The follow is dereferencing a pointer.
    // when you DEreference a pointer, you get a REFERENCE to the object or data it points to.
    int data = *ptr; // dereference the pointer; copy the data into data
    
    std::cout << data << std::endl;
    
    // This is re-assigning the pointer to point to another location in memory (another variable)
    ptr = &b;
    
    std::cout << *ptr << std::endl;
}


____________________________________

The above are rather simple, contrived examples to just demonstrate the syntax of pointers.

In modern C++, you should prefer to use references when passing objects instead of pointers, unless using a pointer is necessary.

To actually know if we want the ptr itself, or *ptr (the data it points to), we have to put it in context. The issue here is that any real example that requires pointers has to be complicated enough to warrant the use of pointers. Linked Lists and Trees are classic examples that use pointers.

But for now, let's go a bit simpler and just swap two variables. In modern C++, you should be pass-by-reference for this, but let's pretend we have to use pointers.

Scenario A:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Example program
#include <iostream>

void swap(int t, int u)
{
    int temp = t;
    t = u;
    u = temp;
}

int main()
{
    int a = 5;
    int b = 3;
    
    std::cout << a << " " << b << std::endl;
    swap(a, b);
    
    std::cout << a << " " << b << std::endl;
}

Run this code. You'll see the output is:
5 3
5 3


Why didn't it swap? This is because when C++ passes an object into a function, it by default does copy-by-value. Only the local copies were swapped, but not the actual data in main.

To actually swap the numbers, we need to work with the actual data in main, and not a copy of them. This is done by passing the addresses of the variables in main, instead of copying the values themselves.
Scenario B:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Example program
#include <iostream>

void swap(int* ptr_a, int* ptr_b)
{
    int temp = *ptr_a;
    *ptr_a = *ptr_b;
    *ptr_b = temp;
}

int main()
{
    int a = 5;
    int b = 3;
    
    std::cout << a << " " << b << std::endl;
    swap(&a, &b);
    
    std::cout << a << " " << b << std::endl;
}

When we call swap(&a, &b) we are passing the addresses of a and b.
The function sees these as pointers. Now, when we dereference ptr_a, using *ptr_a, we are modifying the actual data that the pointer (address) points to.

Long winded and rambly... but hope you get the idea a bit better now.

___________________________________

Also, there really isn't ever a reason to actually print the pointer itself (and print out the address). Might be good for debugging purposes, but the address used is something you can't control.

You can, however, set a pointer to be a "null pointer", which signifies that it's not point to any data. Dereferencing a null pointer causes undefined behavior.
int* ptr = nullptr;
Last edited on
Topic archived. No new replies allowed.