Hello guys can someone explain why while declaring pointers to pointer we need to use ** why cant we use only single * to point a pointer to another pointer or is it just a syntax related issue E.g
int main()
{
int a=5,*b,*c;
b=&a;
c=&b //Why cant this simply doesn't make c point to memory location of b with the above pointer declaration why is there a need to declare c as **c
}
With the following codes:
int a=5,*b,**c;
b=&a;
c=&b;
We have:
+---+
a | 5 | <-- value
+---+
|100| <-- address
+---+
+---+
*b |100| <-- value
+---+
|200| <-- address
+---+
+---+
**c |200| <-- value
+---+
|300| <-- address
+---+
When you store a's address in b, b's value is a's address. But b has it's own address (200).
c can store b's address as it's value. But c has it's own address too (300).
printf("%x", &c); will give you: 300
Deferencing *c will get you down "1 level" and give you 100 (get value of address 200)
Deferencing **c will get you down 1 more level and give you 5 (get value of address 100)
If you try to use *c instead of **c to hold *b, how are you able to deference all the way down to reach value 5?
Testing the codes on a compiler:
printf("Address of a: %x\n", &a);
printf("Address of b: %x\n", &b);
printf("Address of c: %x\n", &c);
printf("Value of a: %d\n", a);
printf("Value of b: %x\n", b);
printf("Value of c: %x\n", c);
Output:
Address of a: 28ff44
Address of b: 28ff40
Address of c: 28ff3c
Value of a: 5
Value of b: 28ff44
Value of c: 28ff40
In this case
int main()
{
int a=5,*b,*c;
b=&a;
c=&b;
}
Here b points to a and c points to b. It is what you have commented in the commented.
c still points to the memory location of b.
The catch is : When you de-reference b i.e *b = a = 5.
But When you de-reference c i.e *c = b = &a. So When you dereference c the output would be address of a instead of the value of the variable a
PS : you will face this warning when compiling the code warning: assignment from incompatible pointer type
Every level of indirection needs a level of dereferencing. So for:
T*** x = ...;
you would need:
***x
to get to T&.
If you had a pointer to pointer and you saved it in:
T* x = ...;
T* y = &x;
it would mean that *ptr leads to T&, while it really leads to another T*.
You have your answer in your question only.
pointer to variable , use of *
pointers to pointer of a variable , use **
Details:
** is not a new operator. it's a combination of * and *. In case 2. as per your terminology, you can think of
only single * to point a pointer to another pointer
as in
int * to an inother int * ==> int **
EDIT:
as per your code
int main()
{
int a=5,*b,*c;
b=&a;
c=&b;
}
b is a pointer to int. You can store the address of int there, and a is an int. Perfect.
c is a pointer to int. You can store the address of int there, and b is a pointer to int. Not accepted.
To make point 2 work, you need to declare c as a pointer to int *, right? The notation for the same is int **.
Here's another way to think of pointers-to-pointers: imagine how it works in memory. Here's a little snippet that shows what I mean:
int TheInteger = 123;
int *p = &TheInteger;
int **pp = &p;
printf("The value at memory location &pp (0x%x) is 0x%x (pp). This value (which we assigned as &p (0x%x) is 0x%x (p). This value, in turn, we assign as &TheInegeter (0x%x) points to the 'instance' of TheInteger, which is %d", &pp, pp, &p, p, &TheInteger, TheInteger);
The output of this would be:
The value at memory location &pp (0x657e588) is 0x657e594 (pp). This value (which we assigned as &p (0x657e594) is 0x657e5a0 (p). This value, in turn, we assign as &TheInegeter (0x657e5a0) points to the 'instance' of TheInteger, which is 123
Now, to go back to your original question, you cannot declare a variable as being a pointer when the value you're setting it to is a pointer-to-a-pointer. In other words, in your example, you set 'b' as a pointer to a -- so, you can't tell the compiler that 'c' is just a pointer and then try to set it to a value that the compiler knows is a pointer-to-a-pointer.
Related
Please explain to me how the b pointer shows the last element.
Every time, it prints out the last element, no matter how long the array is. If you use *b alone in cout, it shows a number out of array.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int a[] = {1,2,3,4,5,6,7,8,9,10,11};
int *b =(int*) (&a+1);
cout << *(b-1) << endl;
return 0;
}
This expression
&a+1
has the type int ( * )[11] and points to the memory after the last element of the array a.
In this declaration
int *b =(int*) (&a+1);
you interpreted the expression as having the pointer type int * that points to after the last element of the array a. Instead you could write
int *b = a + 11;
So the expression
b - 1
points to the last element of the array a.
Thus you may imagine the expression *( b - 1 ) the following way
*( a + 11 - 1 ) => *( a + 10 ) => a[10]
Per pointer arithmetic rules, incrementing/decrementing a pointer by N elements will adjust the value of the pointer by N * sizeof(T) bytes, where T is the dereferenced type of the pointer.
&a is a pointer to the array itself, which has a type of int[11], so you have a pointer of type int(*)[11] to the beginning of the array. Lets call this A1 in the diagram below.
Adding +1 to that pointer will advance it by sizeof(int[11]) (aka sizeof(int)*11) bytes, thus producing a new int(*)[11] pointer to the memory address immediately following the entire array. Let's call this A2 in the diagram.
You are then type-casting that new pointer, so now you have a pointer of type int* to the end of the array. This is the memory address you are assigning to your int *b pointer variable. Lets call this B1 in the diagram below.
Subtracting -1 from that pointer will reduce it by sizeof(int) bytes, thus producing a new int* pointer to the memory address of the last int element in the array. Lets call this B2 in the diagram below.
So, when you dereference b to print the int that it is pointing at, you are printing the value of the last int in the array. If you don't decrement b, it is pointing past the end of the array, and you have undefined behavior. You might just print out random garbage, or you might crash your app. Anything could happen.
---------------------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---------------------------------------------------------------------
^ ^ ^
| | |
|_A1 --------------------------------------------------------|----->|_A2
+1 | |
|_B2 <-|_B1
-1
In http://www.fredosaurus.com/notes-cpp/arrayptr/array-diagrams.html website, it states that
Pointers hold the memory address of other data and are represented by a black disk with an arrow pointing to the data it references.
For example,
int a[5]; // Allocates memory for 5 ints.
. . .
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
would result in.
My question is how can I print the address of the pointer pointing to the array?
I know that &a or &a[0] gives us the address of the first element. But how can I access the pointer pointing the array?
An array and a pointer are not the same thing. What the memory really looks like is this:
a
-------
| 1 | a[0]
-------
| 2 | a[1]
-------
| 4 | a[2]
-------
| 8 | a[3]
-------
| 16 | a[4]
-------
So if you were to print a and &a, you would see that they print the same value.
If the array is on the stack as it would be in your example code then the image below is a more accurate representation of how the memory would be laid out. I've also added an additional pointer to hopefully add some clarification.
int a[5];
a[0] = 1;
for (int i=1; i<5; i++)
a[i] = a[i-1] * 2;
int* b = a;
It may be easier to think of the [] notation of defining an array as a little syntactic sugar. When calling functions and passing in a the function will be called with the address of a[0] being passed in.
When passing b to a function it's the value that will be passed in, which is the address of a.
You can have lots of pointers pointing to a[0].
Just as for a pointer to the array, create a pointer variable pointing to a[0] and then take a pointer to it. You will have one pointer to one pointer pointing to the array.
I know that &a or &a[0] gives us the address of the first element.
Technically. &a is in fact the address of the array itself. It just has the same value as address of the first element. But note that the type of the expression is different. &a is a int (*)[5] (pointer to an array of 5 integers), while &a[0] is a int* (pointer to an integer).
My question is how can I print the address of the pointer pointing to the array?
First step is to have a pointer. You don't have any pointer variables in your example. An array is not a pointer. The sentence "The actual array variable, a in this example, is a pointer to the memory for all of its elements." of the page is very misleading, as an array is not a pointer object. The drawn diagram is not correct for the program.
Here is a program that is correct according to the diagram:
int array[5]; // Allocates memory for 5 ints.
int* a = array; // a pointer to the first element of the array
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
Here we actually have a pointer. Now you can print the address of the pointer:
std::cout << &a;
I thought a[] and *a are the same thing because they work like pointers. Yet I encountered something unexpected in the following code:
#include <iostream>
using namespace std;
class F {
public:
bool a[];
F();
};
F::F() {
*a = new bool[5];
a[2] = true;
}
int main() {
F obj;
if(obj.a[2])
cout << '?';
return 0;
}
This code prints ?, but I don't understand how it works. When:
*a = new bool[5];
is changed into:
a = new bool[5];
compiler reports:
F:\main.cpp|11|error: incompatible types in assignment of 'bool*' to 'bool [0]'|
I found this behaviour weird, so I was playing around with this code. When I changed the type of a from bool to int compiler always reports an error
F:\main.cpp|11|error: invalid conversion from 'int*' to 'int' [-fpermissive]|
Why does this work the way it does?
I thought a[] and *a are the same thing because they work like pointers.
Let's talk about this piece of declaration:
int a[4] = { 1, 2, 3, 5 };
int *b = NULL;
This is how they land in memory in the executable:
+----+----+----+----+
a: | 1 | 2 | 3 | 5 | <-- 4 integers
+----+----+----+----+
+----------+
b: | NULL | <-- 1 pointer that points to nowhere
+----------+
As you can see, they are not the same thing.
What happens after b = new int[4];?
The new memory layout of b is something like this:
+----------+
b: | 0xacf3de | <-- 1 pointer that points to a block of 4 integers
+----------+
Somewhere else in memory (at address 0xacf3de)...
+----+----+----+----+
0xacf3de: | ? | ? | ? | ? | <-- 4 integers
+----+----+----+----+
But wait, somebody told me that arrays work like pointers...
No, that's not true. The arrays do not work like pointers.
An array name (a, f.e.) can be used as a shortcut for its address in memory (which is, in fact, the address of its first element). The following notations are equivalent:
a
&a
&a[0]
The value of all of them is the address in memory where the first element of a (the 1 in the example above) is stored.
a[0] is an int, &a[0] is an int *. This is the complete form. The other two are shortcuts that the language provides in order to make the code easier to read and understand.
The things are different for pointers.
b is the value stored in the b variable (NULL or 0xacf3de in the example above. It is a value of type int * -- the address in memory where an int is stored. &b is the address in memory where (the value of) b is stored. Its type is int ** -- a pointer to a pointer to an int; or "the address in memory where is stored the address of an int".
But wait, they can be replaced one for another in some contexts
Up to some point, yes, a pointer and an array are interchangeable. As you can see above, there is a common data type involved: int *. It is the type of b (which stores the address of an int) and also the type of &a[0] (which is also the address of an int).
This means that where b can be used, a (a short of &a[0]) can be used instead, and vice-versa.
Also, where *b can be used, *a can be used instead. It is the short for *&a[0] and it means "the value (*) stored at the address (&) of a[0]" and it is, in fact, the same as a[0].
But, where &b can be used, &a cannot be used instead; remember that &a is the same as &a[0] and its type is int * (but the type of &b is int **).
The line:
*a = new bool[5];
is equivalent to:
a[0] = new bool[5];
You are not initialiazing your array, but allocating an array of bool which is then implicitly converted into bool to be assigned to a[0]: the value should be true since the pointer returned by new should be different from 0. This implicit conversion does not apply with ints: that is why you are getting an error when changing the type of a.
Now, considering this line:
a = new bool[5];
Here you are trying to assign your dynamically allocated array to a, in other words assigning a pointer to an array bool* to a static array bool[0]: as the compiler says, the types are incompatible. A static array a[] can be used as a pointer, e.g. in the following code:
int foo(bool* a) { /* ... */ }
bool my_array[5];
foo(my_array);
But pointers can not be converted into static arrays as you are trying to do.
Type of value returned from new Type[x] is Type * i.e pointer of that type
examle:
So Right syntax is
bool a;
*a = new bool[x];
so it is wrong to do like is
a=new bool[x] wrong syntax as it is invalid to assign pointer to a normal varibale
see for more details
I thought array and pointer are basically the same thing, until I run this program:
int main() {
int* a = new int(19);
int b[1];
b[0] = 19;
printf("*a: %d\n a: %p\n &a:%p\n", *a, a, &a);
printf("*b: %d\n b: %p\n &b:%p\n", *b, b, &b);
delete a;
}
output is:
*a: 19
a: 0x7f94524000e0
&a:0x7fff51b71ab8
*b: 19
b: 0x7fff51b71ab4
&b:0x7fff51b71ab4
can someone please explain why the output of &b is the same as b?
Thanks!
-Erben
Well, b is an array. Under the slightest excuse it will decay into a pointer to the first element of b. Note, however, that the expression b and &b are not equivalent: b decays into a pointer the first element, i.e., it is of type int* while &b is a pointer to the array, i.e., it is of type int(*)[1].
Arrays and pointers are not the same. A pointer can behave like an array (e.g. accessing by index).
&b is a pointer to the whole array and b is a pointer to the first element. They may point to a same address in memory but they are totally different things.
+-------------------------------+
|+-----+-----+-----+-----+-----+|
|| | | | | ||
&b---->|| 0 | 1 | 2 | ... | N ||
|| | | | | ||
|+-----+-----+-----+-----+-----+|
+---^---------------------------+
|
b
a is a variable. You are allocating memory using new and assigning the result to this pointer. You might decide to store something else in a later in your program.
b is different. It's not a variable in the sense that it cannot store different addresses. It's an array, having a fixed start location.
Thus, b and &b are same. But the contents of a and the actual address of a are different.
This is basically just to help me understand pointers better, so if you guys can confirm/deny/explain anything it looks like I don't understand properly I would be most appreciative. The examples of using mailboxes, and aunts, and streets, and all that crap is just confusing.
int a = 5;
int b = &a; // b will be the memory address of 'a'
int *c = a; // c will be the value of 'a' which is 5
int *d = &a; // d will be a pointer to the memory address of 'a'
int &e = a; // what would this be?
void FunctionA()
{
int a = 20;
FunctionB(&a);
// a is now 15?
}
void FunctionB(int *a)
{
a = 15;
}
Thank you guys for any help, I am just trying to improve my understanding beyond all of the crappy metaphor explanations im reading.
I'll take things one by one:
int b = &a; // b will be the memory address of 'a'
No. The compiler (probably) won't allow this. You've defined b to be an int, but &a is the address of an int, so the initialization won't work.
int *c = a;
No -- same problem, but in reverse. You've defined c to be a pointer to an int, but you're trying to initialize it with the value of an int.
int *d = &a;
Yes -- you've defined d to be a pointer to an int, and you're assigning the address of an int to it -- that's fine. The address of an int (or an array of ints) is what a pointer to int holds.
int &e = a;
This defines e to be a reference to an int and initializes it as a reference to a. It's perfectly legitimate, but probably not very useful. Just for Reference, the most common use of a reference is as a function parameter (though there are other purposes, of course).
void FunctionA() { int a = 20; FunctionB(&a); }
void FunctionB(int *a) { a = 15; }
To make this work, you need to change the assignment in FunctionB:
void FunctionB(int *a) { *a = 15; }
As it was, you were trying to assign an int to a pointer, which won't work. You need to assign the int to the int that the pointer points at to change the value in the calling function.
int &e = a; // what would this be?
e is a reference to a. In this case the ampersand is not the 'address of' operator. You treat e as you would a normal (not a pointer) variable, but the value of e and of a will be the same no matter what you do to either (as long as both remain in scope) as essentially e is just an alias.
int a = 5;
So far so good.
int b = &a; // b will be the memory address of 'a'
That's actually a compilation error. You probably mean int *b=&a;. b is a POINTER to an integer.
edit: If you mean to get the address in numerical form, you need to force the cast to an integer: int b=(int)&a;
int *c = a; // c will be the value of 'a' which is 5
This one is more confusing. At its core, a pointer is just a number, sure, but this kind of assignement is inherently not safe (as you can see, you're assigning 5 to a pointer, and trying to dereference that will most likely crash your program). If you really do want c to point at the memory location 5, you have to explicitly tell the compiler you know what you're doing: int *c=(int *)a.
int *d = &a; // d will be a pointer to the memory address of 'a'
This one is right, same as what you probably mean by the second one.
int &e = a; // what would this be?
e is a "reference" to a. Basically internally it's just a pointer to a, but you don't have to manually dereference it, the compiler handles it for you.
void FunctionA() { int a = 20; FunctionB(&a); // a is now 15? }
Yes.
void FunctionB(int *a) { a = 15; }
...assuming you write this as *a=15;. You're overwriting the VALUE pointed to by a, not the pointer itself.
You seem pretty confused by this overall, I recommend reading the book "Thinking in C++", it's really well written!
You've got plenty of good answers here for your specific example, so I'd like to share a general technique that I used to learn how pointers work when I was starting out.
Get a big sheet of graph paper and lay it lengthwise on the table in front of you. This is your computer's memory. Each box represents one byte. Pick a row, and place the number '100' below the box at far left. This is "the lowest address" of memory. (I chose 100 as an arbitrary number that isn't 0, you can choose another.) Number the boxes in ascending order from left to right.
+---+---+---+---+---+--
| | | | | | ...
+---+---+---+---+---+--
100 101 102 103 104 ...
Now, just for the moment, pretend an int is one byte in size. You are an eight-bit computer. Write your int a into one of the boxes. The number below the box is its address. Now choose another box to contain int *b = &a. int *b is also a variable stored somewhere in memory, and it is a pointer that contains &a, which is pronounced "a's address".
int a = 5;
int *b = &a;
a b
+---+---+---+---+---+--
| 5 | |100| | | ...
+---+---+---+---+---+--
100 101 102 103 104 ...
Now you can use this model to visually work through any other combinations of values and pointers that you see. It is a simplification (because as language pedants will say, a pointer isn't necessarily an address, and memory isn't necessarily sequential, and there's stack and heap and registers and so on), but it's a pretty good analogy for 99% of computers and microcontrollers.
You can extend the model for real four-byte ints too...
int a = 5;
char b = 2;
a a a a b
+---+---+---+---+---+--
| 0 | 0 | 0 | 5 | 2 | ...
+---+---+---+---+---+--
100 101 102 103 104 ...
int &e=a; is a reference to "a".
and these are bugs:
int b = &a;
int *c = a;
I think you mean:
int *b = &a;, which makes a pointer called b that points to the value of a (b is a pointer which is the address of a)
int c = *b;, (or just int c = a if you only want c to have a's value) In this case, * dereferences the pointer b
FunctionA() See below, then a will be 15 (you're passing the address of a to FunctionB)
void FunctionB(int *a) {*a = 15;} sets the value to 15 (* dereferences)