Change pointer to an array to get a specific array element - c++

I understand the overall meaning of pointers and references(or at least I think i do), I also understand that when I use new I am dynamically allocating memory.
My question is the following:
If i were to use cout << &p, it would display the "virtual memory location" of p.
Is there a way in which I could manipulate this "virtual memory location?"
For example, the following code shows an array of ints.
If I wanted to show the value of p[1] and I knew the "virtual memory location" of p, could I somehow do "&p + 1" and obtain the value of p[1] with cout << *p, which will now point to the second element in the array?
int *p;
p = new int[3];
p[0] = 13;
p[1] = 54;
p[2] = 42;

Sure, you can manipulate the pointer to access the different elements in the array, but you will need to manipulate the content of the pointer (i.e. the address of what p is pointing to), rather than the address of the pointer itself.
int *p = new int[3];
p[0] = 13;
p[1] = 54;
p[2] = 42;
cout << *p << ' ' << *(p+1) << ' ' << *(p+2);
Each addition (or subtraction) mean the subsequent (prior) element in the array. If p points to a 4 byte variable (e.g. int on typical 32-bits PCs) at address say 12345, p+1 will point to 12349, and not 12346. Note you want to change the value of what p contains before dereferencing it to access what it points to.

Not quite. &p is the address of the pointer p. &p+1 will refer to an address which is one int* further along. What you want to do is
p=p+1; /* or ++p or p++ */
Now when you do
cout << *p;
You will get 54. The difference is, p contains the address of the start of the array of ints, while &p is the address of p. To move one item along, you need to point further into the int array, not further along your stack, which is where p lives.
If you only had &p then you would need to do the following:
int **q = &p; /* q now points to p */
*q = *q+1;
cout << *p;
That will also output 54 if I am not mistaken.

It's been a while (many years) since I worked with pointers but I know that if p is pointing at the beginning of the array (i.e. p[0]) and you incremented it (i.e. p++) then p will now be pointing at p[1].
I think that you have to de-reference p to get to the value. You dereference a pointer by putting a * in front of it.
So *p = 33 with change p[0] to 33.
I'm guessing that to get the second element you would use *(p+1) so the syntax you'd need would be:
cout << *(p+1)
or
cout << *(++p)

I like to do this:
&p[1]
To me it looks neater.

Think of "pointer types" in C and C++ as laying down a very long, logical row of cells superimposed on the bytes in the memory space of the CPU, starting at byte 0. The width of each cell, in bytes, depends on the "type" of the pointer. Each pointer type lays downs a row with differing cell widths. A "int *" pointer lays down a row of 4-byte cells, since the storage width of an int is 4 bytes. A "double *" lays down a 8-byte per-cell row; a "struct foo *" pointer lays down a row with each cell the width of a single "struct foo", whatever that is. The "address" of any "thing" is the byte offset, starting at 0, of the cell in the row holding the "thing".Pointer arithmetic is based on cells in the row, not bytes. "*(p+10)" is a reference to the 10th cell past "p", where the cell size is determined by the type of p. If the type of "p" is "int", the address of "p+10" is 40 bytes past p; if p is a pointer to a struct 1000 bytes long, "p+10" is 10,000 bytes past p. (Note that the compiler gets to choose an optimal size for a struct that may be larger than what you'd think; this is due to "padding" and "alignment". The 1000 byte struct discussed might actually take 1024 bytes per cell, for example, so "p+10" would actually be 10,240 bytes past p.)

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.

Why do I get different pointer values after an assignment?

so I am currently learning C++ and trying to get a hang of the relationship between arrays and pointers. The code below shows the assignments I have made.
int A[4] = {20, 30, 40, 50};
int p = A[0];
int* q = &p;
Now, if I print out the pointer values, I get this:
A == 0x7ffda1cb1ea0
&A == 0x7ffda1cb1ea0
&A[0] == 0x7ffda1cb1ea0
&p == 0x7ffda1cb1e94
q == 0x7ffda1cb1e94
&q == 0x7ffda1cb1e98
I don't really understand why the values for &A[0] and &p are different, even though the assignment ist p = A[0]. I also don't understand how there are only 4 bytes between q and &q, even though the size of q is shown as 8. Any help would be greatly appreciated.
I don't really understand why the values for &A[0] and &p are different
They are different objects in memory, so they have different addresses. A[4] is one object, p is another one and q is another one. The assignment makes them hold the same value, but they're still two different objects. You can remove the assignment and the result will be the same.
I also don't understand how there are only 4 bytes between q and &q,
even though the size of q is shown as 8
q is set to the address of p, and &p gives you the address of q. The result of 4 makes sense, because that's how big p is. That's why q comes 4 after p, because p takes up 4 bytes.
Perhaps it's more clear if you try the same thing with a reference:
int A[4] = { 20, 30, 40, 50 };
int &p = A[0]; // note the "&", this makes p a reference
std::cout << "&A[0]: " << &A[0] << std::endl << "&p: " << &p << std::endl;
For me, this results in:
&A[0]: 008FFD90
&p: 008FFD90
Now p isn't a separate object that can hold a copy of a data, but an actual reference to the same place.
I don't really understand why the values for &A[0] and &p are different
A[0] and p are separate objects. Each object has an unique address during their life time (except certain cases involving subobjects). The life time of A[0] and p overlap. Therefore &A[0] and &p cannot possibly be the same.
even though the assignment ist p = A[0]
Assignment has no effect on where an object is stored. It can only affect the value that is stored in the object.
also don't understand how there are only 4 bytes between q and &q, even though the size of q is shown as 8
The size of q is irrelevant, since it points to a lower address. The size of p happens to be 4:
/-offset from p
/ object in memory
00 p (first byte) \
01 p |
02 p |
03 p |
04 q (first byte) | Distance between p and q: 4
05 q
06 q
07 q
08 q
09 q
10 q
11 q
When you are doing int p = A[0] you are simply assigning the value of A[0] to p. They are both different objects and are stored at different locations.
The value of &p will not change if you change the value of p.
The gap of 4 is due to the size of p it is not related to the size of q

Arrays and pointers arithmetic confusion

#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}
Fairly new coder here. This is an example taken from the pointers page on cplusplus.com. They talk about dereferencing, the address of operator, and then they talk about the relationship between arrays and pointers. I noticed if I simply printed out a declared array it spits out the address of the array. I'm really trying to understand exactly what some of these lines of code are doing and am having a hard time.
Everything makes sense up until *p=10. I read this as, "the value being pointed to by pointer p is equal to 10" but an array isn't just one value. In this case it's 5... So, whats the deal? Will the compiler just assume we are talking about the first element of the array?
Even more confusing for me is p++;. p right now is the address of the array. How do you do p=p+1 when p is an address?
I understand p= &numbers[2];. As well as the following *p = 30;.
p = numbers + 3; confuses me. Why are we able to take an address and just add 3 to it? And, what does that even mean?
Everything within the for loop makes sense. It's just printing out the array correct?
Thanks for your help in advance!
As Pointed out this due to pointer arithmetic.
So both array numbers and pointer p are int, so after assigning numbers's base address to pointer p and the *p=10 does numbers[0]=10
Now when you do p++ the address of p is incremented but not to the next numeric value as in normal arithmetic operation of ++ but to the address of the next index of numbers.
Let's assume a int is 4byte of memory and numbers's initial address is 1000.
So p++ makes address it to be incremented to 1004 which is numbers[1]
Basically it points to the next int variable position in memory.
So when *p = 20 is encountered the value 20 will be assigned to the next adjacent memory i.e. 1004 or numbers[1]=20.
After that the p directly assigned address of 3rd index numbers[2] i.e 1008 (next int var in memory). Now p is pointing to the 3rd index of numbers so *p=30 is again numbers[2]=30
p = numbers + 3; *p = 40; does similar thing that is assigns base address of numbers incremented by 3 indexes (1000 + 3*sizeof(int) =1012 ==> 1000 + 3*4 =1012) to p and assigns 40 to that. so it becomes equivalent to numbers[3]=40.
Then p = numbers; *(p+4) = 50; is assigning 1000 to p and the adding 4 to the address of p by using the () and assigns 50 to the value by using *() which is value of the address(1000+ 4*4 = 1016) inside the braces.
Using a pointer like this in C++: p = numbers makes p point to the first element of the array. So when you do p++ you are making p point to the second element.
Now, doing *p = 10 assigns 10 to whatever p is pointing to, as in your case p is pointing to the first element of the array, then *p = 10 is the same as numbers[0] = 10.
In case you see this later: *(p + i) = 20, this is pointer arithmetic and is the same as p[i] = 20. That's why p[0] = 10 is equivalent to *(p + 0) = 10 and equivalent to *p = 10.
And about your question: How do you do p=p+1 when p is an address?: as arrays in C++ are stored sequentially in memory, if the element p is pointing at memory address 6400010 then p++ points at 6400014 assuming each element pointed by p occupies 4 bytes. If you wonder why p++ is 6400014 instead of 6400011, the reason is a little magic C++ does: when increasing a pointer, it doesn't increase by 1 byte but by 1 element so if you are pointing to integers, each one occupying 4 bytes, then p will be increased by 4 instead of 1.
Let's break it down:
int numbers[5];
int * p;
Assigning the array variable to a pointer means that the pointer will be pointing to the first element:
p = numbers; // p points to the 1st element
*p = 10; // 1st element will be 10
p++; // go to next location i.e. 2nd element
*p = 20; // 2nd element will be 20
You can do pointer arithmetic and it works according to the type. Incrementing an int pointer on a 32-bit machine will do a jump of 4 bytes in memory. On a 64-bit machine, that will be 8 bytes. Keep in mind that you cannot do this with a void pointer.
p = &numbers[2]; // assign the address of 3rd element
*p = 30; // 3rd element will be 30
p = numbers + 3; // numbers + 3 means the address of 4th element
*p = 40; // 4th element will be 40
p = numbers; // p points to the 1st element
*(p + 4) = 50; // p + 4 means the address of 5th element
// dereference 5th location and assign 50
// 5th element will be 50
There are a lot of pages on the web on how pointers work. But there are a couple things to quickly point out.
int* p;
The above line mean p is a pointer to an int. Assigning something to it doesn't change what it is. It is a pointer to an int, not an array of int.
int number[5];
p = number;
This assignment takes the address where the array is stored, and assigns it to p. p now points to the beginning of that array.
p++;
p now points to the 2nd int in the array. Pointers are incremented by the size of the object they point to. So the actual address may increase by 4 or 8, but it goes to the next address of an int.
*p = 30;
This is an assignment, not a comparison. It doesn't say that what p points to is 30, it copies 30 into the address pointed to by p. Saying "equals" is generally confusing in programming terms, so use either "assign" or "compare" to be clear.
1> p=numbers;
pointer p now points to the start of the array, i.e first element.
2> *p=10;
first element now becomes 10, as p is pointing to the first element.
3> p++;
this moves the pointer to the next element of the array, i.e second element
So, again *p=20; will make second element=20
4> p = &numbers[2];
this statement means that p now points to 3rd element of the array.
So, *p = 30; will make 3rd element=30
5> p = numbers + 3;
Wen we do p=numbers+1; it points to second element, so p=numbers+3; will now point to 4th element of array. *p = 40; make the fourth element=40
6> p = numbers;
Again p points to first element of array
*(p+4) = 50; will now make 5th element=50

Why do you have to specify an index number when assigning a value to the first element in an array?

Why do you have to specify an index number when assigning a value to the first element in an array?
Let's say we had this array:
int childer[] = {10, 30, 50};
then both childer and childer[0] would be accessing the first element of the array, so why can't you dochilder = 15;?
Arrays are similar to pointers. For example an array decays to a pointer when passed to a function, or even when the operators [] and the unary * are applied to them (Thanks StoryTeller). So
childer[0]
is equivalent to
*childer
and you can do
*childer = 15;
to set the first element to 15.
childer
on the other hand is the same as
&childer[0]
childer[0] and childer have two different meanings. childer[0] is the first element of the array while childer is a pointer to the first element. In order to get the first element using the pointer, you have to use *childer.
so,
*childer = 15;
can be used for assignment.
you could dereference the name of the array, but just trying to do
childer = -999;
is completely wrong...
see the example below:
int main() {
int childer[] = { 10, 30, 50 };
cout << childer[0] << endl;
cout << *childer << endl;
//now write
childer[0] = 200;
cout << childer[0] << endl;
cout << *childer << endl;
//now write again
*childer = -999;
cout << childer[0] << endl;
cout << *childer << endl;
return 0;
}
First of all
int childer[] = { 10, 20, 30 };
...
childer = ....; <--- THIS WILL NOT COMPILE, as childer is not an lvalue.
you cannot say childer = 20;, you can say childer[0] = 20; or *childer = 20;, or even more *(childer + 1) = 20; (to access other elements than the first), but you cannot use childer as the whole array in an assignment. Simply, neither C nor C++ allow this.
Arrays and pointers are very different things. What confuses you, is that neither C, nor C++ have a way to reference the array as a whole, and the array identifier, by itself, means the address of the first element (and not a pointer but a reference). What I mean by a reference, and I don't use the word pointer for just now, is that a pointer normally refers to a variable of pointer type, and as a variable, can be modified (mainly because the array position cannot be changed at runtime). You cannot write something like array = something_else;, when array is an array. Array names cannot be used by themselves as lvalues, only as rvalues. This can be done with pointers, like
int childer[] = { 10, 20, 30, };
int *pointer = childer;
and then
pointer = some_other_place_to_point_to;
because pointer is a pointer and childer isn't.
The meaning that both languages attribute to the array name is just a pointer rvalue pointing to the address of the first element (and typed as the cell type, continue reading for an explanation on this). And this is not the same as the address of the array (both are different things, demonstrated below) as the first (the array name is a pointer to cell type, while the array address &childer is a pointer to the whole array type). This can be illustrated with the next program, which tries to show you the difference in sizes for the array element, the whole array, the array pointer and the cell pointer:
#include <stdio.h>
#include <sys/types.h>
#define D(x) __FILE__":%d:%s: " x, __LINE__, __func__
#define P(fmt, exp) do { \
printf(D(#exp " == " fmt "\n"), (exp)); \
} while(0)
#define TR(sent) \
sent; \
printf(D(#sent ";\n"))
int main()
{
int i = 1;
TR(double a[10]);
P("%p", a);
P("%p", &a);
P("%d", sizeof a);
P("%d", sizeof &a);
P("%d", sizeof *a);
P("%d", sizeof *&a);
return 0;
}
which executes into (I selected double as the type of cell to make evident the differences while trying to be more architecture independent):
$ pru
pru.c:16:main: double a[10]; <-- array of ten double's (a double is 8 bytes in many architectures)
pru.c:18:main: a == 0xbfbfe798 <-- address values are
pru.c:19:main: &a == 0xbfbfe798 <-- equal for both.
pru.c:20:main: sizeof a == 80 <-- size of whole array.
pru.c:21:main: sizeof &a == 4 <-- size of array address (that's a pointer to array)
pru.c:22:main: sizeof *a == 8 <-- size of pointed cell (first array element)
pru.c:23:main: sizeof *&a == 80 <-- size of pointed array.
But you are wrong when saying that you cannot use an expression to access the other elements, as you can, use array + 1 to mean the address of the second element, and array + n to access the address of the n + 1 element. Evidently array + 0 is the same as array (the 0 number is also neutral in pointer addition), so you can get on it easily. Some people like to write it for fun also as 0+array (to abuse of the commutativity of the + operator) and go further, to write something like 0[array], to refer to the first element of the array (this time the access being to the element, and not to its address) I don't know if this continues to be valid with the new standards, but I'm afraid it continues, perhaps, to allow for legacy code to be compilable (adding to the controversy of what should be conserved and what can be eliminated on standard revisions)

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