I am trying to get the code to print " 1000 100 10 1" but keep getting "100 10 1 0." Any ideas as to why this is occurring? Any help would be appreciated. Thank you.
#include <iostream>
using namespace std;
int main()
{
int arr[4] = { 0, 1, 2, 3 };
int *ptr;
ptr = arr;
*ptr = arr[0] + 1; // set arr[0] to 1
* ( ptr + 1 ) = arr[ 0 ] * 10; // set arr[1] to 10
* ( ptr + 2 ) = arr[ 0 ] * 100; // set arr[2] to 100
* ( ptr + 3 ) = arr[ 0 ] * 1000; // set arr[3] to 1000
cout << "arr[4] = { " << arr[0] << ", " << arr[1] << ", " << arr[2] << ", " << arr[3] << " }" << endl;
ptr += 3;
while (ptr >= arr)
{
ptr--;
cout << " " << *ptr;
}
cout << endl;
return( 0 );
}
ptr += 3 means you are pointing to arr[3] but you do ptr-- before using the address so your printing actually starts at arr[2]
The end condition is also dangerous as it sets ptr to an address that you "don't own". In theory you are safe because you never use it, but it is still dangerous practice to have pointers with bad values floating around...
I would make it:
ptr += 3; // ptr still points to valid memory
while (ptr >= arr)
{
cout << " " << *ptr;
ptr--; // ptr decremented after use so print starts at arr[3]
}
You moved the pointer to the last element and then get it back to previous element before printing.
Also note that moving pointer back beyond the first element invokes undefined behavior.
Try this:
ptr += 4; // move the pointer one element after the last element (this is allowed unless you dereference it)
while (ptr > arr) // use > instead of >=
{
ptr--;
cout << " " << *ptr;
}
instead of
ptr += 3;
while (ptr >= arr)
{
ptr--;
cout << " " << *ptr;
}
ptr = arr;
ptr points to the first element
ptr += 3;
Now it points to the fourth element at index 3; the last index where value is 1000.
while (ptr >= arr)
We enter the loop.
ptr--;
We now point to the third element, at index 2; where value is 100.
cout << " " << *ptr;
We print the value, which is 100.
If you want to start printing from the last element of the array, you need to get the value from the pointer when it points to the last element; not after you've decremented the pointer.
Related
I find that the value of '*ptr' in the steps:3 does not equal 3
#include <bits/stdc++.h>
using namespace std;
int main(int arg, char* args[])
{
int* ptr;
int x = 4;
float y = 3.142;
cout << y << " " << &y << endl; //step:1
ptr = &x;
cout << ptr << " " << *ptr << endl; //step:2
ptr = (int*)(&y);
cout << ptr << " " << *ptr; //step:3 ->problem here
return 0;
}
ptr = (int*)(&y);
cout << ptr << " " << *ptr; //step:3 ->problem here
The second line invokes undefined behaviour. *ptr dereferences the memory pointed by ptr as if it pointed to an int. Since it doesn't (it points to a float), this is undefined behaviour.
Anything could happen from that point on.
Sample code:
int main()
{
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *j << endl;
}
will print:
4
5
int main()
{
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *(i + 1) << endl;
}
will print:
4
0
Do not get what is the difference
You are lucky or unlucky to get a value in your second code when using cout << *(i + 1) << endl; The i+1 means to move to next location in memory with a length of int. Since you didn't assign anything on the next location. There is no value at that location. It returns 0 but it could be anything!
You use lots of new here to open memory in heap which is not necessary. Many Java users may have habit to use new, but we need to be thoughtful on when to use new in C++. You also need to use delete to release memory if you use new.
Let's check out your code line by line:
int main() {
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *j << endl;
}
// Let's just say that an int is 32bits or 4bytes
int* i = new int(4);
// Declaring a pointer to type int and initializing it with a value of 4
int* j = i + 1;
// Declaring a pointer to type int at 4 memory address location's past i.
// For example: if i's memory address is 0x0004
// then j would be at memory location 0x0008.
// However j will contain any arbitrary value or garbage.
// before calling your next line `j = new int(5);`
// do this:
std::cout << i << " " << j << "\n";
std::cout << *i << " " << *j << "\n;
// Here you will see the address increase by a value of 4 in hex
// which is a 4 byte width provided the int is 32bits or 4bytes
// You will also see that when dereferencing the pointers that the
// memory location that i is point at does have the value 4,
// but the memory location that j is pointing at
// has garbage or any arbitrary value.
// With your next line of code:
j = new int(5);
// now you are taking j and pointing it to another location and assigning
// to that memory location the value of 5.
// You changed where j was pointing in memory.
std::cout << *i << std::endl; // self explanatory: dereferencing i and print value
std::cout << *j << std::endl; // same as above but for j
int main() {
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *(i + 1) << endl;
}
Every line above but the last line is the same. Let's check out the last line.
std::cout << *(i + 1) << std::endl;
// Here you are dereferencing the pointer that is 4 bytes past i.
Basically you are trying to print whatever is stored in memory location 4 bytes on a 32bit machine past i's location in the second part of your code.
If the wording is unclear refer to this picture diagram:
Below is a sample program I created to play around with pointers.
#include <iostream>
using namespace std;
void addOne(int** ptr);
void addTwo(int*** ptr);
void addThree(int**** ptr);
void addFour(int***** ptr);
int main()
{
int* ptr = nullptr;
int x = 1;
ptr = &x;
cout << "Original value of x: " << *ptr << endl;
addOne(&ptr);
cin.get();
return 0;
}
void addOne(int** ptr)
{
**ptr += 1;
cout << "After adding 1: " << **ptr << endl;
addTwo(&ptr);
}
void addTwo(int*** ptr)
{
***ptr += 2;
cout << "After adding 2: " << ***ptr << endl;
addThree(&ptr);
}
void addThree(int**** ptr)
{
****ptr += 3;
cout << "After adding 3: " << ****ptr << endl;
addFour(&ptr);
}
void addFour(int***** ptr)
{
*****ptr += 4;
cout << "After adding 4: " << *****ptr << endl;
}
The program above will give me the following output:
Original value of x: 1
After adding 1: 2
After adding 2: 4
After adding 3: 7
After adding 4: 11
Now focus on the addFour function:
void addFour(int***** ptr)
{
*****ptr += 4;
cout << "After adding 4: " << *****ptr << endl;
}
Now what I did was I reduced the number of *s in the addFour function by doing this:
void addFour(int***** ptr)
{
****ptr += 4;
cout << "After adding 4: " << ****ptr << endl;
}
When I did the above code, it gave me the following output:
Original value of x: 1
After adding 1: 2
After adding 2: 4
After adding 3: 7
After adding 4: 010EFDE0
My question then is, what is the following statements doing since I reduced the number of *s:
****ptr += 4;
cout << "After adding 4: " << ****ptr << endl;
Can someone please explain this for me?
You reduced the dereferencing in addFour to four levels, but the function still takes an int*****.
Most of your code is irrelevant and can be reduced to something like this:
int x = 1;
cout << "Original value of x: " << *&x << endl;
x += 1;
cout << "After adding 1: " << **&&x << endl;
x += 2;
cout << "After adding 2: " << ***&&&x << endl;
x += 3;
cout << "After adding 3: " << ****&&&&x << endl;
x += 4;
cout << "After adding 4: " << *****&&&&&x << endl;
So far your dereference and address-of operations cancel out. But then you're asking what this is:
cout << "After adding 4: " << ****&&&&&x << endl;
Quite simply, you have not performed the final dereference so you're left with &x, not x.
And &x is a pointer. In the example above, you'd be seeing the address of x in memory, given in hexadecimal notation. In your case, your ptr has an unspecified value because pointer arithmetic out of bounds of an object has undefined behaviour, but in practice you're printing the value of the address of x plus sizeof(int).
addOne receives the address of ptr that points to x and store it into a local variable ptr.
addTwo receives the address of addOne::ptr and store it in its local ptr variable.
addThree receives the address of addTwo::ptr and store it in its local ptr variable.
addFour receives the address of addThree::ptr and store it in its local ptr variable. Thus in addFour (second version):
*ptr is addThree::ptr,
**ptr is addTwo::ptr,
***ptr is addOne::ptr and
****ptr is main::ptr.
You then increment a pointer to int by 4, thus calculating the address of the fourth int starting from the address of x, and then print that address.
Of course, in the first version *****ptr is main::x, and you then increment int x by 4.
Trying to visualize this graphically, you have:
P -> P -> P -> P -> P -> X
X is the value, P are pointers.
Every time you write &, you move to the left, and every time you write *, you move to the right.
So if you have &&&&&x, and you increment ****x, you do this:
P -> P -> P -> P -> P -> X
\
> ?
You moved four levels to the right, and incremented the pointer there, which now points to a memory location after X.
Then you print ****x, which is a pointer, because you moved four levels to the right.
// if you want to understand pointers this is my fave example
struct block
{
int data;
struct block *next_block;
};
struct block *block_head = NULL;
add_block(int n) /* add n in the sorted position */
{
struct block *new, *prev = NULL, *bp = block_head;
new = malloc(sizeof(struct block));
new->data = n;
while(bp != NULL)
if(bp->data > n)
{
prev = bp;
bp = bp->next_block;
}
else
{
if(prev == NULL)
{
new->next_block = bp;
block_head = new;
}
else
{
new->next_block = bp;
prev->next_block = new;
}
if(block_head == NULL)
block_head = new;
else
{
prev->next_block = new;
new->next_block = NULL;
}
}
// the above is how you usually do a linked list but it's messy and ugly
// not elegant
// the elegant way to do this is with a double pointer
add_block(int n) /* add n in the sorted position */
{
struct block *new, **bp = &block_head;
new = malloc(sizeof(struct block));
new->data = n;
while(*bp != NULL)
if((*bp)->data > n)
bp = &((*bp)->next_block);
else
break;
new->next_block = *bp;
*bp = new;
}
// if you can understand the elegant version, you probably got pointers down cold.
I am working with tutorials point.com example.
int var[MAX] = {10, 100, 200};
int *ptr;
// let us have address of the last element in pointer.
ptr = &var[MAX-1];
for (int i = MAX; i > 0; i--)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// point to the previous location
ptr--;
}
return 0;
So, why &var[MAX - 1] and why not &var[MAX]? If we do not use a reference, would it be possible to solve this problem in a different manner?
Because arrays in C++ are zero-based, i.e. start from 0 and end at n-1. var[MAX] is the element past the end of the array, so is out-of-bounds and accessing it is undefined behaviour.
var { 10, 100, 200 }
index ^0 ^1^ ^2^ ^3?
If I declare the following variables:
int array[10] = { 34, 43,12, 67, 34, 43,26, 98, 423,1 };
int * p = array;
Then, this loop:
for ( int i = 0; i < 10; i++ )
{
std::cout << &*p++ << " ";
}
gives me different output ( a different set of addresses ), to this code:
for ( int i = 0; i < 10; i++ )
{
std::cout << p++ << " ";
}
Why? Aren't they semantically equivalent?
EDIT:
Well, my apologies to everyone that answered this one, I don't have the original code, it was a test that I did at home and it turns out that I deleted that code from my project. ( my broadband is not yet connected, so I waited till I got to work to post this ). Anyway - I am pretty sure that I was forgetting to initialise p. But the question of "aren't they semantically equivalent?" has been answered. Thanks.
int array[10] = { 34, 43,12, 67, 34, 43,26, 98, 423,1 };
int * p = array;
for ( int i = 0; i < 10; i++ )
{
std::cout << p++ << " ";
}
p = array;
std::cout << '\n';
for ( int i = 0; i < 10; i++ )
{
std::cout << &*p++ << " ";
}
std::cout << '\n';
Gives me the same addresses. Did you accidentally forget p = array; in between?
If you remember to reset p before the second loop, they give the same result.
reset the pointer p's position.
The order of precedence is '++' first, then '*' and finally '&'.
So p++ will output the adresse of array[0] and &*p++ will first increment p, but this is postfix ! So the value of p (and not the value of p+1) will be given to * and then to &, so these are the same
Example:
std::cout << p << std::endl; // Output the adress of p
std::cout << &*p++<<std::endl; // p is increment but it is postfix, so value of p is used and printed
std::cout << &*++p<<std::endl; // p has been increment before and is then incremented again
std::cout << p++ << std::endl; // p has been incremented before, but here p is used first, then incremented