Pointer Syntax Within Condition - c++

After a pointer is initialized, do you have to use the * dereference operator to call the pointer in a condition?
Example:
int main()
{
int var = 10;
int *ptr = &var;
if(ptr) // does this need to be if(*ptr) ???
{.......}
}
And can I have a short explanation as to why?
Thank you.

if (ptr)
check if the pointer is not Null but
if (*ptr)
check if the value it points to is not zero (in this example is 10)
So for checking the value you shoud add *.

It depends on what you want to do.
if(ptr) checks if the pointer value is nullptr or not. Note that this is shorthand for if(ptr != nullptr).
if(*ptr) checks if what the pointer points to is nullptr (or 0) - and in that case, since you dereference (follow) the pointer to answer the question, the pointer itself had better not be nullptr in that case.

First of all, a pointer is only a variable. However, there are different contexts in which you can use it.
As any other variable you can access the pointers content (which is the adress of the underlying memory) as follows:
int i = 1;
int * p = &i;
std::cout << p << std::endl
this would output the adress of i since this is what is stored in p
If you however want to access the content of the underlying memory (the value of i), you need to dereference the pointer first by using the * operator:
std::cout << *p << std::endl;
This would print the value of iso 1.
of course you can also access the pointer's adress (since the adress of i is a numeric value as well and needs to be stored somewhere too):
std::cout << &p << std::endl;
That would output the adress of p so the adress where the adress of i is stored :)
As a little example try to run this code:
#include <iostream>
int main() {
int i = 1;
int * p = &i;
std::cout << "Value of i(i): " << i << std::endl
<< "Adress of i(&i): " << &i << std::endl
<< "Value of p(p): " << p << std::endl
<< "Dereferenced p(*p): " << *p << std::endl
<< "Adress of p(&p): " << &p << std::endl
<< "Dereferenced adress of p(*(&p)): " << *(&p) << std::endl;
}

Related

Pointers and references

I am currently learning c++ and pointers inside of c++. I am curious as to why I get a different memory address when I reference a pointer and why it isn't the same as the reference to the variable. Here is my super simple code:
#include <iostream>
using namespace std;
int main() {
int n = 50;
int *p = &n;
cout << "Number: " << n << endl;
cout << "Number with &: " << &n << endl;
cout << "Pointer: " << p << endl;
cout << "Pointer with *: " << *p << endl;
cout << "Pointer with &: " << &p << endl;
}
Why does &p give me a different address than "&n" and "p"? Thank you
First you declare an int variable n with the value of 50. This value will be stored at an address in memory. When you print n you get the value that the variable n holds.
Then you declare a pointer *p pointing to the variable n. This is a new variable that will hold the address to the variable n, where it is stored in memory. When you print p you will get back that address.
You can also ask for the address to where the value of n is stored by using the & symbol. This is what you get when you print &n, this will be the same as the pointer p.
Using the * symbol before a pointer will dereference it, meaning instead of returning the address that is the pointer, it will return the value that the pointer is pointing to. In your case this is an int with the value 50.
Lastly, the pointer *p that you declared is stored at it's own address in memory. Just as you could get the address to the variable n with the & symbol, you can get the address of p by using &p. This will be different from the address of n since it's not where 50 is stored, it's where the pointer to the value 50 is stored.

Changing the address of a pointer to edit its value

recently we were trying to use pointer to void, by passing a copy of its address to an instance of a class, in order for the instance to allocate it to the same memory space as an OpenCV Mat it contains, and that is contained in a stack of memory shared by the GPU and CPU to compute it with OpenCV+CUDA.
However while doing that we ran into an issue we didn't quite understand. When passing the address of the pointer to the object, we tried to edit that address so that the pointer was hosted on another space. And while that worked once that copy ran out of scope the value of that pointer returned to being what it was (I'll add a code snip since its confusing to even explain it). However if we accessed the content of the pointer's address that we passed to the function, and edit that, the original pointer is edited.
My hypothesis is that when we passed the pointer's address to the function a copy of the value of that memory address is made, and if that pointer to pointer is edited, the content of it is left undisturbed, while on the other function we accessed the content and directly edited it, hence the copy is left undisturbed and runs out of scope, while the content is edited correctly.
Here is a snip of the code where I try both things:
// Example program
#include <iostream>
#include <string>
void change_value(int **p, int *addr)
{
*p = addr;
}
void change_direction(int **p, int *addr)
{
std::cout << "p value: " << p << std::endl;
std::cout << "p contains: " << *p << std::endl;
std::cout << "p contains contains: " << **p << std::endl;
p = &addr;
std::cout << "p value: " << p << std::endl;
std::cout << "p contains: " << *p << std::endl;
std::cout << "p contains contains: " << **p << std::endl;
}
int main()
{
int a = 1, b = 2, c = 3;
int *ptr = &a;
std::cout << "ptr direction: " << &ptr << std::endl;
std::cout << "ptr value: " << ptr << std::endl;
std::cout << "ptr contains: " << *ptr << std::endl;
std::cout << std::endl;
change_value(&ptr, &b);
std::cout << "change_value" << std::endl;
std::cout << "ptr direction: " << &ptr << std::endl;
std::cout << "ptr value: " << ptr << std::endl;
std::cout << "ptr contains: " << *ptr << std::endl;
std::cout << std::endl;
change_direction(&ptr, &c);
std::cout << std::endl;
std::cout << "change_direction" << std::endl;
std::cout << "ptr direction: " << &ptr << std::endl;
std::cout << "ptr value: " << ptr << std::endl;
std::cout << "ptr contains: " << *ptr << std::endl;
}
This is the output we got. We can see that while ptr is edited on change_value function, since we access to the content of p and edit it, it is not changed on change_direction, since the moment we edit p's address it stops pointing to ptr.
ptr direction: 0x710a27e3fe18
ptr value: 0x710a27e3fe0c
ptr contains: 1
change_value
ptr direction: 0x710a27e3fe18
ptr value: 0x710a27e3fe10
ptr contains: 2
p value: 0x710a27e3fe18
p contains: 0x710a27e3fe10
p contains contains: 2
p value: 0x710a27e3fdd8
p contains: 0x710a27e3fe14
p contains contains: 3
change_direction
ptr direction: 0x710a27e3fe18
ptr value: 0x710a27e3fe10
ptr contains: 2
If anyone could offer a better explanation of what happened I'd be most grateful.
Cheers.
Not sure if I understand the question, but if this:
void change_direction(int **p, int *addr)
{
// ...
p = &addr;
// ...
}
Is supposed to modify the parameter passed to the function, then it isnt correct.
Parameters are passed by value unless you pass them by reference. Passing references is recommended, but if you like you can use pointers. However, then you need to modify what the pointer points to, not the pointer. In the function above p is local to the function. Modifying the value of p has no effect outside the function.
You probably want:
void change_direction(int **p, int *addr)
{
// ...
*p = addr;
// ...
}
Or rather
void change_direction(int *&p, int *addr)
{
// ...
p = addr; // p is a reference, hence no dereference needed
// ...
}
Actually you should prefer int*& here, because a nullptr is not a valid paramter (and thats about the only reason you would use a pointer rather than a reference).
#463035818_is_not_a_number offered a good answer that works well.
But there might be value in fully understanding what your original code is doing.
Beggining from the start:
int a = 1, b = 2, c = 3;
int *ptr = &a;
This initializes three pieces of memory in stack memory containing the int values you gave (a,b,c) and one more piece of memory for your ptr variable that holds the address of a.
You then print out the address and the values of ptr, which obviously doesn't change any of the values.
Next is the call to change_value(int **p, int *addr) which executes.
*p = addr;
The parameter p in this case holds an address to an address to an int somewhere in memory, so *p is the address pointed to by p.
Setting that to addr changes the address p points to.
So in your specific code:
change_value(&ptr,&b);
Sets the value of ptr to be the address of b.
Then next is the change_direction(int **p, int* addr) call (which probably should be named change_address), which executes (ignoring the printing):
p = &addr;
This sets the parameter p to be the address of addr.
But since in C/C++ all functions are called by value (in C there arent even any references, in C++ you have to specify it as #463035818_is_not_a_number mentioned), this doesnt do anything to the original values, that the function has been called with.
So the call:
change_direction(&ptr,&c)
Does not actually change what is held in ptr. At the beginning of the call to the function, the address of ptr (so &ptr) gets copied into a piece of stack-memory, which is then used in the function and freed after the function exits.
I hope this clears things up, pointers can be hard to wrap your head around sometimes.
Cheers.

What is the relationship between an array and its address?

The following code:
#include<iostream>
int main (void) {
int lista[5] = {0,1,2,3,4};
std::cout << lista << std::endl;
std::cout << &lista << std::endl;
std::cout << lista+1 << std::endl;
std::cout << &lista+1 << std::endl;
std::cout << lista+2 << std::endl;
std::cout << &lista+2 << std::endl;
std::cout << lista+3 << std::endl;
std::cout << &lista+3 << std::endl;
return (0);
}
Outputs:
0x22ff20
0x22ff20
0x22ff24
0x22ff34
0x22ff28
0x22ff48
0x22ff2c
0x22ff5c
I understood that an array is another form to express a pointer, but we cannot change its address to point anywhere else after declaration. I also understood that an array has its value as the first position in memory. Therefore, 0x22ff20 in this example is the location of the array's starting position and the first variable is stored there.
What I did not understand is: why the other variables are not stored in sequence with the array address? I mean, why lista+1 is different from &lista+1. Should not they be the same?
In pointer arithmetic, types matter.
It's true that the value is the same for both lista and &lista, their types are different: lista (in the expression used in cout call) has type int* whereas &lista has type int (*)[5].
So when you add 1 to lista, it points to the "next" int. But &lista + 1 points to the location after 5 int's (which may not be a valid).
Answering the question as asked:
std::cout << &lista+1 << std::endl;
In this code you take the address of array lista and add 1 to obtained answer. Given the sizeof of the array is sizeof(int) * 5, which means when you increment a pointer to it by 1 you add sizeof(int) * 5 to the pointer address, you end up with a number you see.

What's meaning of &&pointer or &*(pointer_to_pointer) in C++

int *p;
int **pp;
int a = 9;
p = &a;
pp = &p;
cout << "&a: " << &a
cout << "&p: " << &p
cout << "&pp: " << &pp
cout << "pp : " << pp
cout << "*pp: " << *pp
cout << "&*pp: " << &*pp
&&p and &&pp aren't defined in c++ so they are wrong using, but what &*pp is meaning? Is &*pp equalent to &&a?
When the program is starting, the result is as follows:
&a: 00AEFAE4
&p: 00AEFAFC
&pp: 00AEFAF0
pp : 00AEFAFC
*pp: 00AEFAE4
&*pp: 00AEFAFC (=&p ???)
On the other hand, why is &*pp equalent to &p?
you asked what does &*pp means here pp is a double pointer which contains address of the pointer (*p) by writing &*pp firstly you are dereferencing value of **pp
*(pp) which will become value inside pp which is the address of pointer p
by writing &(*pp) now you are trying to get address of the dereferenced value which is (address of p) that will ultimetely become address of p
in simple words where you use both of these operators together they cancel out each other and give you the value present in the pointer
in this case &* will be cancelled out and you will get value of pp which is address of p
i tried to make it as clear as i could.... hope that helps :)

what happens in this block of code?

What happens when I do this? When I remove the first initialization to "boo1", it prints boo2 but now it still prints nothing. Does this mean that the pointer allocate a random memory and assign "boo1" value to it and now I can't access it or what?
string *p;
*p="boo1";
p=new string;
*p="boo2";
cout << *p; //prints nothing
line 1: "p" contains random value, i.e. refers to random memory address.
line 2: random memory block referred by "*p" is interpreted as string instance. This instance is assigned by "boo1".
Try so:
string *p = new string;
*p = "boo1";
cout << *p << '\n';
*p = "boo2";
cout << *p << '\n';
delete p;
Remember that:
std::string is not the same as stupid char[] array!
All pointers must be assigned before usage!
All "new" must have corresponding "delete"!
If you declare a string as pointer ( string *p ), you must allocate memory for it,
so the correct way to do the job is:
string *p = new string;
*p = "boo1";
cout << *p << '\n';
*p = "boo2";
cout << *p << '\n';
The previous answers are correct, however why not using a reference, it seems more convenient in your case.
Something like :
std::string p;
p = "boo1";
std::cout << p << std::endl;
p = "boo2";
std::cout << p << std::endl;
Regards,
Michel.