Pointer syntax usage in Array - c++

I have some problem understanding the pointers syntax usage in context with two dimensional arrays, though I am comfortable with 1-D array notation and pointers, below is one of the syntax and I am not able to understand how the following expression is evaluated.
To access the element stored at third row second column of array a we will use the subscripted notation as a[2][1] other way to access the same element is
*(a[2]+1)
and if we want to use it as pointers we will do like this
*(*(a+2)+1)
Though I am able to understand the replacement of *(a[2]+1)
as *(*(a+2)+1) but I don't know how this is getting evaluated.
Please explain with example if possible.
Assume array is stored in row wise order and contain the following elements
int a[5][2]={
21,22,
31,32
41,42,
51,52,
61,62
};
and base address of array is 100(just assume) so the address of a[2] is 108 (size of int =2(another assumption)) So the expression *(*(a+2)+1). How does it gets evaluated does it start from the inside bracket and if it does then after the first bracket we have the value to which 1 is being added rather than the address... :/

To start of with
a[i] = *(a+i);
So
a[i][j] = *(a[i] +j)
and
a[i][j] = *(*(a+i) + j)
How a[i] = *(a+i):
If a is a array then the starting address of the array is given by &a[0] or just a
So when you specify
a[i] this will decay to a pointer operation *(a+i) which is, start at the location a and dereference the pointer to get the value stored in the location.
If the memory location is a then the value stored in it is given by *a.
Similarly the address of the next element in the array is given by
&a[1] = (a+1); /* Array decays to a pointer */
Now the location where the element is stored in given by &a[1] or (a+1) so the value stored in that location is given by *(&a[1]) or *(a+1)
For Eg:
int a[3];
They are stored in the memory as shown below:
a a+1 a+2
------------------
| 100 | 102 | 104|
------------------
&a[0] &a[1] &a[2]
Now a is pointing to the first element of the array. If you know the pointer operations a+1 will give you the next location and so on.
In 2D arrays the below is what the access is like :
int arr[m][n];
arr:
will be pointer to first sub array, not the first element of first sub
array, according to relationship of array & pointer, it also represent
the array itself,
arr+1:
will be pointer to second sub array, not the second element of first sub
array,
*(arr+1):
will be pointer to first element of second sub array,
according to relationship of array & pointer, it also represent second
sub array, same as arr[1],
*(arr+1)+2:
will be pointer to third element of second sub array,
*(*(arr+1)+2):
will get value of third element of second sub array,
same as arr[1][2],

A 2D array is actually a consecutive piece of memory. Let me take a example : int a[3][4] is representend in memory by a unique sequence of 12 integer :
a00 a01 a02 a03 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24
| | |
first row second row third row
(of course it can be extended to any muti-dimensional array)
a is an array of int[4] : it decays to a pointer to int[4] (in fact, it decays to &(a[0]))
a[1] is second row. It decays to a int * pointing to beginning of first row.
Even if arrays are not pointer, the fact that they decay to pointers allows to use them in pointer arithmetic : a + 1 is a pointer to second element of array a.
All that explains why a[1] == *(a + 1)
The same reasoning can be applied to a[i] == *(a+i), and from there to all the expressions in your question.
Let's look specifically to *(*(a+2)+1). As said above, a + 2 is a pointer to the third element of an array of int 4. So *(a + 2) is third row, is an array of int[4] and decays to a int * : &(a[2][0]).
As *(a + 2) decays to an int *, we can still use it as a base for pointer arithmetic and *(a + 2) + 1 is a pointer to the second element of third row : *(a + 2) + 1 == &(a[2][1]). Just dereference all that and we get
*(*(a + 2) + 1) == a[2][1]

Related

How can I subtract from elements in an array with pointer notation?

I have a prompt asking me to declare and initialize an array of 4 doubles and to create a pointer to the array. Then I should add 30.0 to the second physical element of the array through the pointer via array notation. After, I should subtract 10.0 from the last array element through the pointer using pointer notation. Then I should reassign the pointer to the last element of the array.
I have tried figuring out how to subtract with pointer notation but no dice. I’m not following what needs to be done.
Here’s my code so far:
int main () {
double arr[4] = {10.0, 15.0, 20.0, 25.0};
double *p = &arr;
p[1] = 30.0; //array notation
//code should go here for the subtracting ten part
//code should go here assigning pointer to last element of array.
//My idea of how this would look:
p = (p + 3); // or 15.0
//or:
p = arr[3];
}
I tried doing something like (p+3) -=10.0 but I have a feeling that’s wrong.
What I think the outcome should be: my arr elements being {10.0, 30.0, 20.0, 15.0} and p pointing to last element of array.
So array notation is really syntactic sugar over pointer arithmetic. In your code:
p[1] = 30.0;
Can also be written as
*(p + 1) = 30.0;
Similarly, if you want to "subtract 10.0 from the last array element through the pointer using pointer notation"
You would do this:
double *p = arr
*(p + 3) -= 10.0
Explanation:
When you are declaring an array you are declaring a series of values stored in contiguous memory (that means memory blocks next to each other). The reason you are able to access different elements in that array is that you know
Where the array starts
How far along you want to move
So really, array notation arr[2] (where arr is an array of doubles) means "Go to the memory address of array arr, move along 2 * sizeof(double), then give us the value stored there. Funnilly enough, that's exactly what *(p + 2) means, only it's broken down - the bit inside the brackets means "move along 2", and the star (the "dereference operator") means give us the value.

How are 2-Dimensional Arrays stored in memory?

#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[101][101];
a[2][0]=10;
cout<<a+2<<endl;
cout<<*(a+2)<<endl;
cout<<*(*(a+2));
return 0;
}
Why are the values of a+2 and *(a+2) same? Thanks in advance!
a is a 2D array, that means an array of arrays. But it decays to a pointer to an array when used in appropriate context. So:
in a+2, a decays to a pointer to int arrays of size 101. When you pass is to an ostream, you get the address of the first element of this array, that is &(a[2][0])
in *(a+2) is by definition a[2]: it is an array of size 101 that starts at a[2][0]. It decays to a pointer to int, and when you pass it to an ostream you get the address of its first element, that is still &(a[2][0])
**(a+2) is by definition a[2][0]. When you pass it to an ostream you get its int value, here 10.
But beware: a + 2 and a[2] are both pointers to the same address (static_cast<void *>(a+2) is the same as static_cast<void *>(a[2])), but they are pointers to different types: first points to int array of size 101, latter to int.
I'll try to explain you how the memory is mapped by the compiler:
Let's consider a more pratical example multi-dimentional array:
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
You can execute the command
x/10w a
In GDB and look at the memory:
0x7fffffffe750: 1 2 3 4
0x7fffffffe760: 5 6 7 8
0x7fffffffe770: 9 0
Each element is stored in a int type (32 bit / 4 bytes).
So the first element of the matrix has been stored in:
1) a[0][0] -> 0x7fffffffe750
2) a[0][1] -> 0x7fffffffe754
3) a[0][2] -> 0x7fffffffe758
4) a[1][0] -> 0x7fffffffe75c
5) a[1][1] -> 0x7fffffffe760
6) a[1][2] -> 0x7fffffffe764
7) a[2][0] -> 0x7fffffffe768
...
The command:
std::cout << a + 2 << '\n'
It will print the address 0x7fffffffe768 because of the
pointer aritmetic:
Type of a is int** so it's a pointer to pointers.
a+2 is the a[0] (the first row) + 2. The result is a pointer
to the third row.
*(a+2) deferences the third row, that's {7,8,9}
The third row is an array of int, that's a pointer to int.
Then the operator<< will print the value of that pointer.
A 2-dimensional array is an array of arrays, so it's stored like this in memory:
char v[2][3] = {{1,3,5},{5,10,2}};
Content: | 1 | 3 | 5 | 5 | 10 | 2
Address: v v+1 v+2 v+3 v+4 v+5
To access v[x][y], the compiler rewrites it as: *(v + y * M + x) (where M is the second dimension specified)
For example, to access v[1][1], the compiler rewrites it as *(v + 1*3 + 1) => *(v + 4)
Be aware that this is not the same as a pointer to a pointer (char**).
A pointer to a pointer is not an array: it contains and address to a memory cell, which contains another address.
To access a member of a 2-dimensional array using a pointer to a pointer, this is what is done:
char **p;
/* Initialize it */
char c = p[3][5];
Go to the address specified by the content of p;
Add the offset to that address (3 in our case);
Go to that address and get its content (our new address).
Add the second offset to that new address (5 in our case).
Get the content of that address.
While to access the member via a traditional 2-dimensional array, these are the steps:
char p[10][10];
char c = p[3][5];
Get the address of pand sum the first offset (3), multiplied by the dimension of a row (10).
Add the the second offset (5) to the result.
Get the content of that address.
If you have an array like this
T a[N];
then the name of the array is implicitly converted to pointer to its first element with rare exceptions (as for example using an array name in the sizeof operator).
So for example in expression ( a + 2 ) a is converted type T * with value &a[0].
Relative to your example wuth array
int a[101][101];
in expression
a + 2
a is converted to rvalue of type int ( * )[101] and points to the first "row" of the array. a + 2 points to the third "row" of the array. The type of the row is int[101]
Expression *(a+2) gives this third row that has type int[101] that is an array. And this array as it is used in an expression in turn is converted to pointer to its first element of type int *.
It is the same starting address of the memory area occupied by the third row.
Only expression ( a + 2 ) has type int ( * )[101] while expression *( a + 2 ) has type int *. But the both yield the same value - starting address of the memory area occupied by the third row of the array a.
The first element of an array is at the same location as the array itself - there is no "empty space" in an array.
In cout << a + 2, a is implicitly converted into a pointer to its first element, &a[0], and a + 2 is the location of a's third element, &a[2].
In cout << *(a + 2), the array *(a + 2) - that is, a[2] - is converted into a pointer to its first element, &a[2][0].
Since the location of the third element of a and the location of the first element of the third element of a are the same, the output is the same.

Multi-dimensional arrays and pointers in C++

Let's say I declare and initialize the following multi-dimensional array in C++:
unsigned a[3][4] = {
{12, 6, 3, 2},
{9, 13, 7, 0},
{7, 4, 8, 5}
};
After which I execute this code:
cout << a << endl; // output: 0x7fff5afc5bc0
cout << a + 1 << endl; // output: 0x7fff5f0afbd0
cout << *a << endl; // output: 0x7fff5afc5bc0
cout << *a + 1 << endl; // output: 0x7fff5f0afbc4
I just don't understand what is happening here.
a is the address of the first element, right? In single-dimensional arrays, *a should be the value of the first element, but instead it's the same as a?! What does *a even mean in this context?
Why is a + 1 different from *a + 1?
You should try and find some good documentation about pointers, arrays, and array-to-pointer decay. In your case, unsigned a[3][4] is a bi-dimensional array of type unsigned [3][4]. Whenever you refer to it as a, it decays to a pointer to unsigned[4], so the decayed type of a is unsigned (*)[4]. Therefore dereferencing it gives you an array, so *a is the array [12, 6, 3, 2] (technically it's the pointer to the first element into the array).
Now, a+1 means "increment the pointer to unsigned[4] by 1", in your case it "jumps" 4 unsigneds in the memory, so now a+1 points to the "row" indexed by 1 in your example. Dereferencing it *(a+1) yields the array itself ([9,13,7,0]) (i.e. the pointer to the first element of it), and dereferencing again gives you the first element, i.e. **(a+1) equals 9.
On the other hand, *a+1 first dereferences a, so you get the first row, i.e. [12,6,3,2] (again, technically the pointer to the first element of this row). You then increment it by one, so you end up pointing at the element 6. Dereferencing it again, *(*a+1), yields 6.
It may be helpful to define a equivalently as
typedef unsigned T[4]; // or (C++11) using T = unsigned[4];
T a[3]; // Now it's a bit more clear how dereferencing works
Two dimensional array is array of array.
You can visualize a as
a = { a[0], a[1], a[2]}
and a[0], a[1], a[2] as
a[0] = { a[0][0], a[0][1], a[0][2], a[0][3]};
a[1] = { a[1][0], a[1][1], a[1][2], a[1][3]};
a[1] = { a[2][0], a[2][1], a[2][2], a[2][3]};
Analysis of your first question
a is the address of the first element, right?
Yes a is the address of the first element, and first element of a is a[0] which is the address of the first element of a[0][0].
*a should be the value of the first element, but instead it's the same as a?
Yes *a should be the value of the first element that refer a[0]. And we see a[0] is the address of a[0][0] so as a . Thus *a have same value as a which is the address of a[0][0].
What does *a even mean in this context?
Previously answered, *a is the address of first arrays first element a[0][0], and *(a+1) is the address of second arrays first element a[1][0].
And analysis of your second question
Why is a + 1 different from *a + 1?
At this time perhaps you can answer your owns question.
a is the address of a[0] then
a+1 is the address of a[1] which hold address of a[1][0].
You can print the value by
cout<<**(a+1)<<endl; // 9
Other way *a is the value of a[0] which is the address of a[0][0].
So *a+1 is the address of a[0][1]. You can print the value as
cout<<*(*a+1)<<endl; // 6

Convert int to int pointers address

c++
p is pointing to specific place
int * p
When I try p=p[1] it says can't convert int to int (using devcpp).
While p=&p[1] works fine
Why do I need to do the second method?
p[1] is an address. So the first method should work?
Can you explain me about this error?
p[1] is the same as *(p + 1).
You want the address of this element, which is simply (p + 1). C++ also allows &p[1], as you noticed.
p[1] is equivalent to *(p + 1) so it's a value, not an address. p = p + 1 or just p++ would be what you want.
While p is anint*, p[1] is an element from that array, therefore p[1] is int.
You can do p = &p[1] in other ways, for instance, p = p + 1, or p++. Both will set p to the same final value.
Notice when doing such arithmetic operations with pointers, it will not not increment the address by 1, its incrementing it by 1 times the size of one element, so its really the same thing.

Pointer arithmetic and dereferencing

In the following code, can anyone please explain to my what the line in bold is doing.
struct southParkRec {
int stan[4];
int *kyle[4];
int **kenny;
string cartman;
};
int main()
{
southParkRec cartoon;
cartoon.stan[1] = 4;
cartoon.kyle[0] = cartoon.stan + 1;
cartoon.kenny = &cartoon.kyle[2];
*(cartoon.kenny + 1) = cartoon.stan; //What does this line do?
return 0;
}
Think of it as
cartoon.kenny[1] = cartoon.stan;
They are basically the same thing
If we bring the whole thing to one common style of using the subscript operator [] (possibly with &) instead of a * and + combination, it will look as follows
cartoon.stan[1] = 4;
cartoon.kyle[0] = &cartoon.stan[1];
cartoon.kenny = &cartoon.kyle[2];
cartoon.kenny[1] = &cartoon.stan[0];
After the
cartoon.kenny = &cartoon.kyle[2];
you can think of kenny as an "array" of int * elements embedded into the kyle array with 2 element offset: kenny[0] is equivalent to kyle[2], kenny[1] is equivalent to kyle[3], kenny[2] is equivalent to kyle[4] and so on.
So, when we do
cartoon.kenny[1] = &cartoon.stan[0];
it is equivalent to doing
cartoon.kyle[3] = &cartoon.stan[0];
That's basically what that last line does.
In other words, if we eliminate kenny from the consideration ("kill Kenny"), assuming that the rest of the code (if any) doesn't depend on it, your entire code will be equivalent to
cartoon.stan[1] = 4;
cartoon.kyle[0] = &cartoon.stan[1];
cartoon.kyle[3] = &cartoon.stan[0];
As for what is the point of all this... I have no idea.
In cartoon you have:
- stan, an array of 4 ints.
- kyle, an array of 4 pointers to int.
- kenny, a pointer to a pointer to int, that is, let's say, a pointer to an "array of ints".
cartoon.stan[1] = 4; sets second element of stan array (an int) to 1.
cartoon.kyle[0] = cartoon.stan + 1; sets first element of kyle array (a pointer to int) to point to the second element of stan array (which we have just set to 4).
cartoon.kenny = &cartoon.kyle[2]; sets kenny pointer to point to the third element of kyle array.
*(cartoon.kenny + 1) = cartoon.stan; sets fourth element of kyle array (a pointer to int) to point to the first element of stan array (which hasn't been initialised yet). More in detail:
cartoon.kenny gets kenny pointer's address (third element of kyle array),
cartoon.kenny+1 gets the next int after that address (fourth element of kyle array, which happens to be a pointer to int),
*(cartoon.kenny + 1) dereferences that pointer, so we can set it, and
= cartoon.stan sets it to point to the first element of stan array.
It is incrementing the pointer at *cartoon.kenny. 'kenny' is a pointer to a pointer, so the first dereference returns a pointer, which is incremented, and a value assigned. So, *(kenny + 1) now points to the beginning of the array 'stan'.
It sets the last element of Kyle to point to the first element of Stan.