views:

379

answers:

5

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 the "virtual memory location?" 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 hypothetically do &p + 1 and obtain the value of p[1] by doing cout << *p, since *p is now a pointer to the second element in the array.

int *p;
p = new int[3];

p[0] = 13;
p[1] = 54;
p[2] = 42;
+5  A: 

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.

KTC
Just wanted to point out that the address of an int will be 4-byte aligned, so it would not have the address 12345. :-)
0124816
It doesn't *have* to. You just don't want to deal with all the issues that arise when the variables isn't align correctly. :D A compiler could in theory ignore alignment and just emit code to deal with accessing incorrectly aligned variables.
KTC
+2  A: 

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.

freespace
If you meant "cout << **q;" then yes. Just make sure you have saved the initial value of p somewhere (or recalculate it), or deleting those dynamically allocated memory is going to be fun. :D
KTC
Hrm, I am not sure why i want cout << **q; that is the same as *p since q points to p, so *q is value of p, and **q == *p? I would be grateful if you point out my error.
freespace
Sorry, you're right. It just appeared weird to me that you got q, start manipulating it via q, and then go back to using p to access the thing.
KTC
freespace
+1  A: 

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)
Guy
+1  A: 

I like to do this:

&p[1]

To me it looks neater.

Adam Pierce
A: 

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.)

Kevin Little