Suppose *ptr points to a variable. What does *ptr, &ptr, and ptr each mean?
Many times, I get confused between them. Do anyone mind clarifying between those statements and give some concrete examples?
Take the following variables in a function.
int i = 0;
int* ptr = &i;
In the function, the memory layout could look something like:
Memory corresponding to i:
+---+---+---+---+
| 0 |
+---+---+---+---+
^
|
Address of i
Memory corresponding to ptr:
+---+---+---+---+
| address of i |
+---+---+---+---+
^
|
Address of ptr
In the above scenario,
*ptr == i == 0
ptr == address of i == address of memory location where the vale of i is stored
&ptr == address of ptr == address of memory location where the value of ptr is stored.
Hope that makes sense.
Here is a computer memory:
int i = 1023
If I want to print i, then I just have to do:
printf(..., i);
// out: 1023
If I want to print where i lives, then I just have to do:
printf(..., &i);
// out: 0x4
But let's say I want to remember where i lives:
int *i_ptr = &i; // i_ptr is a variable of type int *
Then I can print it this way:
printf(..., i_ptr);
// out: 0x04
But if just print out the value of i, I need a *:
printf(..., *i_ptr); // * also doubles as a way to follow the pointer
// out: 1023
Or I can just print out where i_ptr lives:
printf(..., &i_ptr);
// out: 0x32
Given the declarations
int i = 0x01234567;
int *ptr = &i;
the following are true:
Expression Type Value
---------- ---- -----
ptr int * Address of i
*ptr int Value stored in i (0x01234567)
&ptr int ** Address of ptr variable
In memory, it would look something like the following (assuming 32-bit int)
Item Address 0x01 0x02 0x03 0x04
---- ------- ---- ---- ---- ----
i 0x7fffbb00 0x01 0x23 0x45 0x67
ptr 0x7fffbb04 0x7f 0xff 0xbb 0x00
So the value of ptr is 0x7fffbb00, the value of &ptr is 0x7fffbb04, and the value of *ptr is 0x01234567.
Let's suppose you have:
int number = 5;
int *ptr = &number;
ptr will be the variable, of type int *, instead storing a 5 or
"foo", it will store an address like 0xf0f0f004 or whatever it is the
address of the variable number.
*ptr will be the value of what it is in this address of memory 0xf0f0f004, in this specific case is 5.
&ptr will be the address where it is located the variable that will
be in other place for example 0xff00ffaa or whatever.
ptr and number are located in different places in memory, both stores values, one just store a number and the other store an address. And the language allows you putting *, access the value of this address.
If *ptr points to a variable, then that would mean that *ptr is a pointer itself. That would mean you're declaring ptr as follows: int **ptr;
In this case:
ptr is a pointer to the pointer to your variable
*ptr is the pointer to your variable
&ptr gives you the address of ptr, so a pointer to the pointer to the pointer to your variable
For example:
//set up work
int x;
int *intermediatePtr;
int **ptr;
x = 5;
intermediatePtr = &x; //used only for additional level of indirection in this example
ptr = &intermediatePtr; //ie *ptr = &x;
//should print out the memory address for the pointer to the address of x
printf("%d", ptr);
//should print out the memory address of x (different memory location than above)
printf("%d", *ptr);
//should print out the memory address of the variable
//which holds the memory address of x
//(again, different memory location than both above examples)
printf("%d", &ptr);
If ptr points to a variable instead of *ptr (ie int *ptr; ptr = &x;), there is one less level of indirection than my above example.
int *ptr; // declares a pointer to integer.
int val; // declares an integer.
&val; // pointer to val
ptr = &val; // ptr will now point to val
*ptr = 5; // same as writing val = 5
ptr++; // pointer to the next int after val (in this case, it will be undefined behaviour, it is useful if this pointer pointed to a cell in an array)
int arr[10]; // declares an array of size 10
ptr = arr; // ptr now points to arr[0] (name of an array can be implicity cast to pointer to first element)
ptr++; // ptr now points to arr[1]
& = Reference
* = De reference
ptr is the identifier/name. You declare it by int *ptr.
Here is a small C program:
#include<stdio.h>
int main()
{
int *ptr,ref;
ptr= &ref;
ref=12;
printf("%d\n",*ptr );
}
In C,int *ptr is an integer pointer. You can use other data types like float, char etc,.
ptr = &ref gets the address of ref and stores in ptr. Since we declared ptr as integer pointer, when we print the value pointed, we have to De-reference it by using *.
Related
Actually I was reading about pointers and wanted to try something ,so I wrote a small code
int main(){
int x = 10;
int *ptr;
ptr = &x;
printf("%d is stored at address %d\n",x,ptr );
int *c=*ptr;
c=&ptr;
printf("location is %d\n",c);
printf("value of c= %d",*c);
}
the result I expected was value of c would be 10 but instead the value came as the location of x.
output: 10 is stored at address 997523644 location is 997523648 value of c= 997523644
does this problem arise because I didnt pass any location as first?or is it something else or my question is quite silly I know:D,Can anyone help me?
The first thing that is missing in the code that you have provided, is the declaration of ptr. You haven't declared the ptr variable yet, so first you need to do
int *ptr;
, which tells that you need a pointer variable to point to a int variable.
Since you declare another pointer int *c and ptr is already a pointer, you only need to assign int *c = ptr (or c=ptr in case you want to declare int *c seperately first), which will store the value of ptr (location of x) to c. So, doing int *c=*ptr is wrong. Now you can access the value of x by doing derefencing (*c or *ptr), which you already did.
Doing c=&ptr is also wrong, because c is of type int * and &ptr is of type int **. In case you are trying to store the address of ptr, you have to first declare a variable of type int **, for example int **d. Now d=&ptr is valid and d holds a value which is the address of ptr. Dereferencing d (*d) should give you the value that the address of ptr is holding, which is nothing but the address of x (same as the value of c). If you dereference d twice (**d), you should get the back the value of x (10).
int* c = ptr should be enough, you can read it as: c is pointer to integer, c = ptr since ptr is already a pointer this will make both c and ptr point to the same value.
What you are currently doing: c=&ptr; is making c point to the address of ptr, so if you want to access x value you will need to dereference twice, once to get the address of ptr, and once again to get the content of x.
Changed it to this:
#include <stdio.h>
int main(void) {
int x = 10;
int *ptr = &x;
printf("%d is stored at address %p\n",x,ptr );
int *c=ptr;
int d = &ptr;
printf("location is %p\n", c);
printf("value of c= %d", *c);
return 0;
}
As ptr is an address already, you can just do it:
int *c=ptr;
Output is:
10 is stored at address 0x7ffd6127dd54
location is 0x7ffd6127dd54
value of c= 10
To print variable address, you can check this answer:
Stackoverflow Answer
You just need to remove the line
c=&ptr;
The above line means that you're setting C as the location of ptr, which is some random value. So C points to the location of ptr, and ptr points to the location of x. C is a double-pointer
Alternatively, if you keep that line in there, you can make it work by instead printing
printf("value of c= %d",**c);
either solution would get the output you expect
Why does this code output: 1 ≡ arr[0] and not &arr[0]?
My assumption is that after the assignment, ptr holds the address of &arr, which is a pointer to the first element of arr or arr[0].
So dereferencing the ptr should yield the value stored at that address, which is the memory location of the first element.
#include<stdio.h>
int main(void) {
int arr[] = { 1 };
int* ptr = &arr;
printf("%d\n", *ptr);
return 0;
}
A couple of things...
First, a doesn't store the location of a[0]. There is no object a that is separate from the array element a[0]. Basically what you have in memory is
Address
------- +------+
0x1000 a: | 0x01 | a[0]
+------+
In other words, the address of an array is the same as the address of its first element.
Unless it is the operand of the sizeof or unary & operators, the expression a will be converted ("decay") from type "1-element array of int" (int [1]) to "pointer to int" (int *) and the value of the expression will be the address of the first element in the array.
This means that the expressions &a, a, and &a[0] all yield the same address value; it's just the types of the expressions are different:
Expression Type Decays to
---------- ---- ---------
&a int (*)[1]
a int [1] int *
&a[0] int *
Which brings us to this line:
int* ptr = &arr; // int * = int (*)[1] - assignment of incompatible types
The compiler should have yelled at you about that line. You may want to dial up the warning level.
I added some print statements to your code:
#include<stdio.h>
int main(void) {
int arr[] = { 1 };
int *ptr = (int *)arr;
printf("%p\n", (void *)arr);
printf("%p\n", (void *)&arr);
printf("%p\n", (void *)&arr[0]);
printf("%p\n", (void *)ptr);
printf("%p\n", (void *)&ptr);
printf("%d\n", *ptr);
return 0;
}
It prints:
0x7ffe3fe37aa4
0x7ffe3fe37aa4
0x7ffe3fe37aa4
0x7ffe3fe37aa4
0x7ffe3fe37a98
1
Which means arr and ptr are on the stack: ptr is at 0x7ffe3fe37a98 and has the value 0x7ffe3fe37aa4, which is where the arr is stored.
Note that arr and &arr have the same value. See this question: How come an array's address is equal to its value in C?
My assumption is that after the assignment, ptr holds the address of &arr, which is a pointer to the first element of arr or arr[0].
That is correct.
So dereferencing the ptr should yield the value stored at that address
Also correct.
which is the memory location of the first element.
No. Since ptr is pointing to the first element, dereferencing yields the first element, which is 1.
Suppose *ptr points to a variable. What does *ptr, &ptr, and ptr each mean?
Many times, I get confused between them. Do anyone mind clarifying between those statements and give some concrete examples?
Take the following variables in a function.
int i = 0;
int* ptr = &i;
In the function, the memory layout could look something like:
Memory corresponding to i:
+---+---+---+---+
| 0 |
+---+---+---+---+
^
|
Address of i
Memory corresponding to ptr:
+---+---+---+---+
| address of i |
+---+---+---+---+
^
|
Address of ptr
In the above scenario,
*ptr == i == 0
ptr == address of i == address of memory location where the vale of i is stored
&ptr == address of ptr == address of memory location where the value of ptr is stored.
Hope that makes sense.
Here is a computer memory:
int i = 1023
If I want to print i, then I just have to do:
printf(..., i);
// out: 1023
If I want to print where i lives, then I just have to do:
printf(..., &i);
// out: 0x4
But let's say I want to remember where i lives:
int *i_ptr = &i; // i_ptr is a variable of type int *
Then I can print it this way:
printf(..., i_ptr);
// out: 0x04
But if just print out the value of i, I need a *:
printf(..., *i_ptr); // * also doubles as a way to follow the pointer
// out: 1023
Or I can just print out where i_ptr lives:
printf(..., &i_ptr);
// out: 0x32
Given the declarations
int i = 0x01234567;
int *ptr = &i;
the following are true:
Expression Type Value
---------- ---- -----
ptr int * Address of i
*ptr int Value stored in i (0x01234567)
&ptr int ** Address of ptr variable
In memory, it would look something like the following (assuming 32-bit int)
Item Address 0x01 0x02 0x03 0x04
---- ------- ---- ---- ---- ----
i 0x7fffbb00 0x01 0x23 0x45 0x67
ptr 0x7fffbb04 0x7f 0xff 0xbb 0x00
So the value of ptr is 0x7fffbb00, the value of &ptr is 0x7fffbb04, and the value of *ptr is 0x01234567.
Let's suppose you have:
int number = 5;
int *ptr = &number;
ptr will be the variable, of type int *, instead storing a 5 or
"foo", it will store an address like 0xf0f0f004 or whatever it is the
address of the variable number.
*ptr will be the value of what it is in this address of memory 0xf0f0f004, in this specific case is 5.
&ptr will be the address where it is located the variable that will
be in other place for example 0xff00ffaa or whatever.
ptr and number are located in different places in memory, both stores values, one just store a number and the other store an address. And the language allows you putting *, access the value of this address.
If *ptr points to a variable, then that would mean that *ptr is a pointer itself. That would mean you're declaring ptr as follows: int **ptr;
In this case:
ptr is a pointer to the pointer to your variable
*ptr is the pointer to your variable
&ptr gives you the address of ptr, so a pointer to the pointer to the pointer to your variable
For example:
//set up work
int x;
int *intermediatePtr;
int **ptr;
x = 5;
intermediatePtr = &x; //used only for additional level of indirection in this example
ptr = &intermediatePtr; //ie *ptr = &x;
//should print out the memory address for the pointer to the address of x
printf("%d", ptr);
//should print out the memory address of x (different memory location than above)
printf("%d", *ptr);
//should print out the memory address of the variable
//which holds the memory address of x
//(again, different memory location than both above examples)
printf("%d", &ptr);
If ptr points to a variable instead of *ptr (ie int *ptr; ptr = &x;), there is one less level of indirection than my above example.
int *ptr; // declares a pointer to integer.
int val; // declares an integer.
&val; // pointer to val
ptr = &val; // ptr will now point to val
*ptr = 5; // same as writing val = 5
ptr++; // pointer to the next int after val (in this case, it will be undefined behaviour, it is useful if this pointer pointed to a cell in an array)
int arr[10]; // declares an array of size 10
ptr = arr; // ptr now points to arr[0] (name of an array can be implicity cast to pointer to first element)
ptr++; // ptr now points to arr[1]
& = Reference
* = De reference
ptr is the identifier/name. You declare it by int *ptr.
Here is a small C program:
#include<stdio.h>
int main()
{
int *ptr,ref;
ptr= &ref;
ref=12;
printf("%d\n",*ptr );
}
In C,int *ptr is an integer pointer. You can use other data types like float, char etc,.
ptr = &ref gets the address of ref and stores in ptr. Since we declared ptr as integer pointer, when we print the value pointed, we have to De-reference it by using *.
If I run the following on OS X:
int main (void)
{
int* n; // initialise(declare) pointer
*n = 20; // the value in address pointed to by n is 20
printf("n: %i, n&: %i\n", n, &n);
return 0;
}
I get:
n: 1592302512, n&: 1592302480
Why the differing values?
Why do pointer and &pointer have different values?
The expression &n yields the address of n itself, while n evaluates to the value of the pointer, i.e. the address of the thing it points to.
But note that you have undefined behaviour First of all, because you are de-referencing an uninitialized pointer. You need to make n point somewhere you can write to.
For example,
int* n;
int i = 42;
n = &i;
// now you can de-reference n
*n = 20;
Second, you have the wrong printf specifier for &n. You need %p:
printf("n: %i, &n: %p\n", n, &n);
int* n declares a variable called n which is a pointer to an integer.
&n returns the address of the variable n, which would be a pointer to a pointer-to-integer.
Let's say we have the following code:
int a = 20; // declare an integer a whose value 20
int* n = &a; // declare a pointer n whose value is the address of a
int** p = &n; // declare a pointer p whose value is the address of n
In this case we would have the following:
variable name | value | address in memory
a | 20 | 1592302512
n | 1592302512 | 1592302480
p | 1592302480 | who knows?
In your code
int* n; //initialization is not done
*n = 20;
invokes undefined behavior. You're trying to de-reference (write into) uninitialized memory. You have to allocate memory to n before de-referencing.
Apart form that part,
n is of type int *
&n will be of type int **
So, they are different and supposed to have different values.
That said, you should use %p format specifier with printf() to print the pointers.
Just as an alternative, let me spell this out a different way.
char *ptr;
char c='A';
ptr = &c;
In this code, here's what's happening and what values are found when we qualify ptr in different ways.
ptr itself contains the address in memory where the char c variable is located.
*ptr dereferences the pointer, returning the actual value of the variable c. In this case, a capital A.
&ptr will give you the address of the memory location that ptr represents. In other words, if you needed to know where the pointer itself was located rather than what the address is of the thing that it points to, this is how you get it.
In the book it explains:
ptr = &a /* set ptr to point to a */
*ptr = a /* '*' on left:set what ptr points to */
They seem the same to me, aren't they?
No. The first one changes the pointer (it now points at a). The second one changes the thing that the pointer is pointing at.
Consider:
int a = 5;
int b = 6;
int *ptr = &b;
if (first_version) {
ptr = &a;
// The value of a and b haven't changed.
// ptr now points at a instead of b
}
else {
*ptr = a;
// The value of b is now 5
// ptr still points at b
}
Well, no. But to explain the similar behaviour, Adding to Oli Charlesworth's answer:
Consider:
int a = 5;
int* ptr = new int;
if(first_version) {
ptr = &a;
//ptr points to 5 (using a accesses the same memory location)
} else {
*ptr = a;
//ptr points to 5 at a different memory location
//if you change a now, *ptr does not change
}
edit: sorry for using new (c++ not c) but the pointer thing does not change.
No, in ptr = &a you are storing the address of variable 'a' in variable 'ptr'
i.e., something like ptr=0xef1f23.
in *ptr = a you are storing the value of variable 'a' in pointer variable '*ptr'
i.e., something like *ptr=5.
Both are not same.
If u modify the value of a = 10. Then print again *ptr. It will print only 5. not 10.
*ptr = a; //Just copies the value of a to the location where ptr is pointing.
ptr = &a; //Making the ptr to point the a
*ptr=&a C++ compiler will genrate error becoz u r going to assign addres to adres
ptr=&a,this is true here ptr working like variable and &a is a addres of a which contain some value
check and try
int *ptr,a=10;
ptr=&a;output=10;
*ptr=&a signifies that our pointer is pointing towards address of the variable a
while
*ptr=a signifies that our pointer is pointing towards value a
*ptr = &a is not technically correct.
int *ptr = &a; is correct ..... Way (i)
(or)
int *ptr;
ptr = &a; is correct ..........Way (ii)
Here *ptr is a pointer to integer datatype.
int *ptr;
*ptr = a; This means ptr becomes a NULL pointer [i.e. it does not point to any memory location]. *ptr holds the value of a.