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.
Related
When using the address transfer of function, View address blocks of formal parameters and actual parameters, I find that the arguments and formal parameters of array share one address block, while the arguments and formal parameters of variables use two address block. What is the reason?
The code is as follows:
#include<iostream>
using namespace std;
void test(int *i,int * arr) {
cout << &i << endl;
cout << arr << endl;
}
int main() {
int i = 1, arr[2] = {1,2};
cout << &i << endl;
test(&i, arr);
cout << arr << endl;
system("pause");
return 0;
}
And this is the output:
0000008986B6FC54
0000008986B6FC30
0000008986B6FC78 //Arrays use the same space
0000008986B6FC78
You are passing pointers to the functions. The value of the pointers are not modified, ie in the function they point to the same objects as they do in main.
However, you are not printing what you think you print:
void test(int *i,int * arr) {
cout << &i << endl;
cout << arr << endl;
}
The pointer i gets the parameter &i (the i from main). Hence printing i in main will yield the same value as printing i in test. However, you are printing the adress of i in the function not the value of it. If you change your code to:
void test(int *i,int * arr) {
cout << &i << endl;
cout << i << endl;
cout << arr << endl;
}
You will notice the difference. I suggest you to rename at least one of the is in your code, because using same name for different entities can and does cause confusion. The i in test holds the value of the address of the i in main. That does not mean that they are the same, but rather i in test has the same value as &i in main.
In short: &i == &i but you expect &(&i) to be the same as &i.
There is no difference between passing a pointer to the int or passing a pointer to the first element of the array. From the point of view of the function they are both just pointers to int.
Note that test prints the value of arr but the location of i.
In test, &i is the location of its argument i.
That argument's value is the location of the i in main.
You will see this if you print i instead of &i.
arr, on the other hand, is implicitly converted into a pointer to its first element, and you are both passing &arr[0] to test to print, and printing &arr[0] in main.
Here is the same thing with explicit conversions and without using a function:
int main() {
int i = 1, arr[2] = {1,2};
cout << &i << endl;
// Create the "argument"...
int *p = &i;
// These two lines are 'test'...
cout << &p << endl;
cout << &arr[0] << endl;
// and this is after the function call.
cout << &arr[0] << endl;
}
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.
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;
}
My code:
#include <iostream>
using namespace std;
int main() {
char *test = (char*)malloc(sizeof(char)*9);
test = "testArry";
cout << &test << " | " << test << endl;
test++;
cout << &test << " | " << test << endl;
return 1;
}
Result:
004FF804 | testArry
004FF804 | estArry
I don't understand how it's possible that I had moved my array pointer and address didn't change.
The pointer did change. You're just not printing it. To print the pointer test:
cout << (void*) test << endl;
&test is the memory location where test is stored.
test is the value that you incremented with test++ (i.e., you didn't increment &test).
When you do cout << test the overload of operator<< that gets picked is one that takes a const char* and treats it as a C-style string, printing the characters it points to. The cast to void* avoids this behavior in order to print the actual value of test, instead of the value it points to.
In this statement
cout << &test << " | " << test << endl;
expression &test yields the address of the variable test itself that is evidently is not changed. It is the value stored in the variable was changed.
If you want to output the value of the variable test that is the value that points inside the string literal you should write
cout << ( void * )test << " | " << test << endl;
Take into account that there is a memory leak in the program because after allocating memory the pointer is reassigned. And sting literals have types of constant character arrays. So the pointer test should be declared like
const char *test;
Why after using strdup(value) (int)value returns you different output than before?
How to get the same output?
My short example went bad, please use the long one:
Here the full code for tests:
#include <stdio.h>
#include <iostream>
int main()
{
//The First Part
char *c = "ARD-642564";
char *ca = "ARD-642564";
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are equal
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
//The Second Part
c = strdup("ARD-642564");
ca = strdup("ARD-642564");
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are NOT equal Why?
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
int x;
std::cin >> x;
}
Because an array decays to a pointer in your case, you are printing a pointer (ie, on non-exotic computers, a memory address). There is no guarantee that a pointer fits in an int.
In the first part of your code, c and ca don't have to be equal. Your compiler performs a sort of memory optimization (see here for a full answer).
In the second part, strdup allocates dynamically a string twice, such that the returned pointers are not equal. The compiler does not optimize these calls because he does not seem to control the definition of strdup.
In both cases, c and ca may not be equal.
"The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1." source
So it's quite understandable that the pointers differ.