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.
Related
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.
This is what i have:
void g(int *&x) {
int a = 3;
x = &a;
}
void h(const int *&x) {
int b = 2;
x = &b;
}
int main() {
int *p = new int;
*p = 5;
g(p);
cout << p << " " << *p << endl; // Print #2
cout << p << " " << *p << endl; // Print #3
const int*p1 = p;
h(p1);
cout << p << " " << *p << endl; // Print #4
cout << p << " " << *p << endl; // Print #5
}
From what i understand, Print#2 and Print#3 should have the same result but it isn't when i compile it. It goes for Print#4andPrint#5 too. Can someone help me?
Updated : This is the output looks like when i compiled it on my computer:
00EFF9D4 3 //1
00EFF9D4 1552276352 //2
00EFF9D4 2 //3
00EFF9D4 1552276352 //4
shouldn't (1) and (2) be the same ? (3) and (4) either.
I assume you mean int a in g().
Your function make the pointer point to a local variable, which after the termination of the function, will go out of scope.
You then dereference the pointer, which invokes Undefined Behavior.
This is for a lab I have done, which is to create a simple queue using C++.
#include "Task5.h"
#include <iostream>
using namespace std;
void push(const long &i, node* &n) {
if (n == NULL) {
node *ptr = new node;
ptr -> item = i;
ptr -> next = NULL;
n = ptr;
cout << "Created New Node." << endl;
}
else {
node *ptr = n;
cout << "Created Pointer" << endl;
while (ptr -> next != NULL){
cout << "Finding Next..." << endl;
ptr = ptr -> next;
}
cout << "I'm here." << endl;
node *temp = new node;
temp -> item = i;
ptr -> next = temp;
cout << "Node Created." << endl;
}
}
long pop(node* &n) {
if (n == NULL) cout << "HEY!!! Can't pop an empty queue." << endl;
else {
long val;
node *ptr = n;
n = n -> next;
val = ptr -> item;
delete ptr;
return val;
}
}
int main() {
node *head = NULL;
push(13,head);
push(10,head);
push(18,head);
push(22,head);
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
}
This is giving the following output:
Created New Node.
Created Pointer
I'm Here.
Node Created.
Created Pointer
Finding Next...
I'm here.
Node Created.
Created Pointer
Finding Next...
Finding Next...
I'm here.
Node Created.
13
10
18
22
HEY!!! Can't pop an empty queue.
6296192
HEY!!! Can't pop an empty queue.
6296192
So the end result is that the code works, HOWEVER it outputs 6296192 randomly. I thought maybe I misspell something or cout is converting endl; to hex. My lab instructor also has no idea what's happening. Can someone tell me what is happening? If it helps, I am running this code via Linux-run terminal.
Thanks in advance.
In your function:
long pop(node* &n) {
you don't return anything in case of n == NULL is true. So this is UB, and might also cause such random values in output.
I'd suggest using the debugger with a breakpoint on the first cout << pop(head) << endl; and watch the value returned from pop each time.
Also the compiler is probably giving you a warning about the cause of the issue, always pay attention to the warnings it usually means something unintended will happen.
The cout << pop(head) << endl; uses the value returned by pop() but in the case of an empty queue there is no value returned, resulting in undefined behavior.
I'm working on a function to swap pointers and I can't figure out why this isn't working. When I print out r and s in the swap function the values are swapped, which leads me to believe I'm manipulating a copy of which I don't understand because I pass by reference of p and q.
void swap(int *r, int *s)
{
int *pSwap = r;
r = s;
s = pSwap;
return;
}
int main()
{
int p = 7;
int q = 9;
swap(&p, &q);
cout << "p = " << p << "q= " << q << endl;
return 0;
}
Prints: p = 7q = 9
Inside your swap function, you are just changing the direction of pointers, i.e., change the objects the pointer points to (here, specifically it is the address of the objects p and q). the objects pointed by the pointer are not changed at all.
You can use std::swap directly. Or code your swap function like the following:
void swap(int *r, int *s)
{
int temp = *r;
*r = *s;
*s = temp;
return;
}
The accepted answer by taocp doesn't quite swap pointers either. The following is the correct way to swap pointers.
void swap(int **r, int **s)
{
int *pSwap = *r;
*r = *s;
*s = pSwap;
}
int main()
{
int *p = new int(7);
int *q = new int(9);
cout << "p = " << std::hex << p << std::endl;
cout << "q = " << std::hex << q << std::endl << std::endl;
swap(&p, &q);
cout << "p = " << std::hex << p << std::endl;
cout << "q = " << std::hex << q << std::endl << std::endl;
cout << "p = " << *p << " q= " << *q << endl;
return 0;
}
Output on my machine:
p = 0x2bf6440
q = 0x2bf6460
p = 0x2bf6460
q = 0x2bf6440
p = 9 q= 7
The line r=s is setting a copy of the pointer r to the copy of the pointer s.
Instead (if you do not want to use the std:swap) you need to do this
void swap(int *r, int *s)
{
int tmp = *r;
*r = *s;
*s = tmp;
}
You passed references to your values, which are not pointers. So, the compiler creates temporary (int*)'s and passes those to the function.
Think about what p and q are: they are variables, which means they are slots allocated somewhere in memory (on the stack, but that's not important here). In what sense can you talk about "swapping the pointers"? It's not like you can swap the addresses of the slots.
What you can do is swap the value of two containers that hold the actual addresses - and those are pointers.
If you want to swap pointers, you have to create pointer variables, and pass those to the function.
Like this:
int p = 7;
int q = 9;
int *pptr = &p;
int *qptr = &q;
swap(pptr, qptr);
cout << "p = " << *pptr << "q= " << *qptr << endl;
return 0;
You are not passing by reference in your example. This version passes by reference,
void swap2(int &r, int &s)
{
int pSwap = r;
r = s;
s = pSwap;
return;
}
int main()
{
int p = 7;
int q = 9;
swap2(p, q);
cout << "p = " << p << "q= " << q << endl;
return 0;
}
Passing by reference is not the same as passing by value or by pointer. See C++ tutorials on the web for an explanation. My brain is too small to waste cells storing the fine details I can find on the web easily.
If you are into the dark arts of C I suggest this macro:
#define PTR_SWAP(x, y) float* temp = x; x = y; y = temp;
So far this has worked for me.
Could you have a look at what I've faced: http://sdrv.ms/WgafvN
And another screenshot: http://sdrv.ms/UZIp6H
The text of my function is:
bool print_all_points(POINT** pointer)
{
if (pointer == NULL||is_array_empty(pointer))
{
cout << "The array of points is empty." << endl << endl;
return false;
}
else
{
int n = _msize(pointer)/sizeof(pointer[0]);
cout << "The list of points: " << endl<< endl;
cout << "id (x, y)" << endl;
cout << "----------" << endl;
for (int i = 0; i < n; i++)
{
cout << (*pointer[i]).id << " (" << (*pointer[i]).x << ", " << (*pointer[i]).y << ")" << endl;
}
}
return true;
}
This function is expected to print out all the points in an array. My problem is that it perfectly prints the array of 3 points rather than that of 4 points. At the 4th point it bites the dust.
I can't catch what the trouble is.
From the picture it is visible that:
1. All 4 elements of the array are present.
2. It is correctly determined that there 4 of them.
What is the problem?
Could you give me a kick here?
ADDED LATER.
The function which calls this:
POINT** new_point(POINT** pointer, int occup)
{
char x;
char y;
system("cls");
cout << "INPUT A NEW POINT" << endl << endl;
cout << "Input x: ";
cin >> x;
cout << "Input y: ";
cin >> y;
size_t m;
if (pointer != NULL)
{
m = _msize(pointer);
}
POINT * tmp_point = new POINT();
(*tmp_point).id = occup;
(*tmp_point).x = x-48;
(*tmp_point).y = y-48;
POINT** pn = new POINT * [occup];
int necessary_memory = occup * 4; // ???? 4 is the size of a pointer.
if (occup !=1)
{
memcpy(pn, pointer, necessary_memory);
}
POINT ** tmp = new POINT * [occup];
pn[occup - 1] = tmp_point;
memcpy(tmp, pn, occup * sizeof(POINT));
delete[] pn;
pn = tmp;
size_t n = _msize(pn);
cout << endl;
print_all_points(pn);
return pn;
}
several problems:
not copying enough data in 64-bit
int necessary_memory = occup * 4;
should be
int necessary_memory = occup * sizeof(POINT*);
copying too much data
memcpy(tmp, pn, occup * sizeof(POINT));
should be:
memcpy(tmp, pn, occup * sizeof(POINT*));
Someone else can chime in, but I am not sure _msize should be used on memory allocated by new. Is that right? http://msdn.microsoft.com/en-us/library/z2s077bc(v=vs.80).aspx
fucntion in the title should be function
You're welcome. You owe me a beer.
Oh yea, I found my shoes... where would you like it?