Swap integers using pointers - c++

Consider the function :
void swap (int *p,int *q)
{
int temp;
temp=*p;
*p=*q;
*q=temp;
}
swap(4 , 5)
Output:
5 4
I am aware that this is the right way to swap two integers using pointers, as mentioned in the books. But what is actually going on in there? It's very confusing. Consider this function , where the step *p=*q is replaced by p=q i.e., with the indirection operator * removed .
void swap (int *p,int *q)
{
int temp;
temp=*p;
p=q;
*q=temp;
}
Now ,what would happen? In this case the output i get for
swap(4 , 5)
Output:
4 4

Think of an int as a box with a number in it, and think of a pointer as an entry on your clipboard telling you which box to look in.
When you do
*p = *q;
you're looking on your list to find out which box you should use for p, and which box you should use for q; then you're looking what number is in the q box, and copying it into the p box. You still have two separate boxes, and two separate entries on your clipboard; it's just that the two boxes have the same number in.
But when you do
p = q;
you're not touching the boxes at all. You're only changing your clipboard. You're looking up which box you should use for q, and then you're scrubbing out the entry for p on your clipboard and replacing it with the same entry that you found under q. Now you have two boxes, with different numbers in; but your clipboard contains two entries that are the same, and both direct you to the same box. One of your boxes is now unreachable (you don't have an entry on your clipboard pointing you to it), and whenever you look up p or q, you'll end up looking in the same box.
(It's worth noting that this clipboard is only used for executing this particular function, and it gets thrown away afterwards. Changes that you make to the pointers that you pass in as arguments to the function won't have any effect after the function has finished executing. But I'd get your head round the other concepts first off, before you start worrying about scope.)

Because you've removed the step where the int 5 is moved to *p, so you're only moving the 4 across to *q via temp.

Note that int *p and int *q are pointers (represent memory addresses!!). So, when you write p=q you end-up with two pointers that point to the same address!!!
void swap (int *p,int *q)
{
int temp;
temp=*p; // temp = 4
p=q; // p points at the same address with q (where 5 is stored)
*q=temp; // store 4 where q points
}
You now understand that both pointers point to a memory location where integer 4 has been stored! Both pointers point to the same memory location.

In general, the best method for understanding what happens in code with pointers is to bring out a pencil and some paper and start drawing.
I used my computer for this, which is much, much slower.
Since swap(4,5) doesn't actually work, I'll assume that we have two variables in the code that calls swap:
int x = 4;
int y = 5;
swap(&x, &y);
The first two lines of swap are identical in both versions, so the first two pictures apply to both.
As you enter swap, it will look something like this:
As you can see, p points at x, and q points at y.
The value of temp is indeterminate.
Now we have followed the p pointer (*p) and copied the value of x into temp.
Version one:
Here, we follow the pointer q (*q), fetching the value of y (i.e. 5) and then we follow the pointer p (*p) and store that value into x.
And lastly, we follow q so we can store the value of temp, i.e. the value that x used to have, in y.
Version two
Here, we copy the value of q into p.
Since p and q are pointers, they now point to the same thing (y).
As you can see, the variable x hasn't changed; we just changed p so it points somewhere else.
This step is exactly the same as in the first version: store the value of temp in y by following q.
Hope this makes it clearer.

your program will crash because you are passing constant value swap(4,5); and there is no address for 4 and 5what p and q gonna point?
void swap(int *p,int *q){
......
}
expecting two variable to whom pointer p and q can point.

Copy this code to your code editor and test run it. Try to understand what this code is doing using comments.
//Start from main() function
#include <iostream>
using namespace std;
// We are here from main function
/*
This function takes two arguments
both are pointer of type int. When declaring
a pointer of type int we write "int *x". Which means
that the vaiable x is pointer and it can only hold
an address of a varible instead of it's value.
However, We now have addresses of p in x and
q in y. We want to exchange values but taking
addresses of them instead. This is a bit confusing.
*/
void swap(int *x, int *y)
{
int temp = 0;
/*
Things are more confusing in the line below.
" * " is a multipurpose operator.
1. When you put this operator in the middle
of two variable (like a*b ) then it works as a
multipliyer.
2. When you put it when declaring a variable
( like int *x ) then it works as if you are
declaring a pointer of type int.
3. When you put it before a pointer variable name but not
declaring the pointer variable then it gives the
value the pointer pointing to.
In our case the third statement is happening. As x has
the address of p, *x means the value of p.
*/
temp = *x; // Here, *x = 10 (because p = 10) so temp = 10.
/*
Here, we are replacing the value of *x (or p, which is 10)
by *y (or q which is 20).
So, after the execution of the line below
we will have *x = 20 or p = 20. It means we are losing
the previous value of p. This is the reason we kept the value
of p in temp.
*/
*x = *y; // Now p = 20 and q = 20
/*
The line below sets *y (or q ) to the value of temp
(which is 10).
*/
*y = temp; //Now p = 20 and q = 10
}
int main()
{
int p = 0;
int q = 0;
cout << "Enter p : ";
cin >> p; // Say you have entered 10. Now p = 10
cout << "Enter q : ";
cin >> q; // Say you have entered 20. Now q = 20
/*
This line takes you to the swap function above.
We are not sending p, q here. We are sending pointer
or addresses of p and q.
*/
swap(&p, &q); // This line takes you to the swap function above.
cout << "p : " << p << endl;
cout << "q : " << q << endl;
return 0;
}

The function which works correctly:
void swap (int *p,int *q)
{
int temp; //You take an integer variable
temp=*p; //You store the value pointed to by p to temp which is 4
*p=*q; //You copy the value pointed to by q to p which is 5, hence p points to 5
*q=temp; //You store the value in temp as the value pointed by q, hence q points to 4 as temp holds 4
}
Now the code with your changes:
void swap (int *p,int *q)
{
int temp;
temp=*p; //You store the value pointed to by p to temp which is 4
p=q; //p and q are addresses, you equate them so the value pointed becomes equal, if you make change in one the other changes automatically. So basically the value of 'p' in the calling function doesn't change, the change is a local change as the arguments to the called function are passed by reference. So the calue pointed to by p is not altered in 'swap' function.
*q=temp; //Now to make the value pointed to by q as 4
}

You can use the xor swap algorithm:
#include <stdio.h>
int main(int argc, char** argv)
{
int i = 1;
int j = 2;
int *p = &i;
int *q = &j;
printf("BEFORE: %d - %d\n", *p, *q);
if (*p != *q)
{
/* swap */
*p ^= *q;
*q ^= *p;
*p ^= *q;
}
printf("AFTER: %d - %d\n", *p, *q);
return 0;
}
reference:
http://en.wikipedia.org/wiki/XOR_swap_algorithm

Related

Why would you add to an address?

I'm in a data structures course, our midterm is coming up and our practice midterm asks if each line is valid syntax:
int num = 10;
int *p, *q;
p = &num;
q = p; //valid
*p = q; //invalid, int* cannot be assigned to int
(*p)++; //valid
&num+1; //valid ********
p++; //valid ********
So the last two lines of code, as I understand it, add 1 to the address of the num variable.
What purpose would this have in coding?
In this case, that would lead to undefined behavior. It would address the int that follows num in memory, but there is no defined way to tell what that would be. Nonetheless, it is valid syntax.
It would make a great deal more sense if your pointer pointed to an element of an array instead of a scalar. In that case, addressing the next int is reasonable. But in both cases the syntax is valid.
A purpose this would have in coding is to write tests such as:
void f ( size_t length, int data[length] )
{
assert( 0 == length % 4 );
for ( int* p = data; p < data + length; p += 4 )
do_stuff_with_subarray( p, 4 );
return;
}
The loop condition p < data + length bounds-checks the pointer by comparing it to the address one past the end of the array. Dereferencing this address would be undefined behavior, but comparing to it is not. (In this simplistic example, though, there will be UB if do_stuff_with_subarray() ever reads past the end of an array whose length is not divisible by 4.)

Beginner C++ programmer, confused over dynamic arrays

I am trying to create a class analogous to the built-in vector class in C++. I have tried to follow all the instructions in Walter Savitche's textbook, but just can't get it to work properly.
The code was written using the Code::Blocks IDE and compiled using the gcc compiler.
The thing I think I'm missing is the relationship between array parameters and a pointer that points to an array.
This is what I understand about normal variables:
int *p1, *p2, *p3, *p4, a;
a = 5; // variable of type int with value 5
p1 = &a; // p1 now points to the value 5
p2 = p1; // p2 now also points to the value of a
p3 = new int; // p3 points to an anonamous variable of type int with undefined value
*p3 = *p1 // value of variable changed to the value of a, namely 5, but doesn't point to a
p4 = new int; // p4 points to an anonamous variable of type int with undefined value
*p4 = 5; // value of variable changed to 5
p4 = p1 // p4 now also points to the value of a
This is what I essentially don't understand about arrays and pointers that point to arrays
int *p1, *p2, *p3, *p4, a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
p1 = a; // p1 points to the exactly the same thing as a
p2 = new int[3]; // p2 points to an array of base type int with undefined values
p2[0] = 8; // is this the correct usage? is p2 "dereferenced"
p2[1] = 9;
p2[2] = 10;
p2[2] = p1[2]; // again is this correct? is the third element of the array pointed to by p2 now equal to 6?
*p3 = a // what does this mean?
p4 = new int[4]; // p4 points to an array of base type int with undefined values
p4[0] = p2[0];
p4[1] = p2[1];
p4[2] = p2[2];
p4[3] = 3
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?
For completeness sake my class is defined as follows:
class VectorDouble
{
public:
// constructors
VectorDouble(); // default constructor
VectorDouble(int init_count); // user specified
VectorDouble(const VectorDouble& vd_object); // copy constructor
// destructor
~VectorDouble();
// accessors
int capacity_vd(); // get max_count
int size_vd(); // get amt_count
double value_at(int index); // get value of "value" at index i
// mutators
void push_back_vd(double put_at_end); // insert new element at end of "value"
void reserve_vd(int incr_capacity); // set max_count
void resize_vd(int incr_size); // set amt_count
void change_value_at(double d, int index); // set value of "value" at index i
// overloaded =
void operator =(const VectorDouble& vd_object_rhs);
// other
friend bool operator ==(VectorDouble vd_object1, VectorDouble vd_object2);
private:
double *value; // pointer that points to array of type double
int max_count; // the memory allocated to the array
int amt_count; // the amount of memory in use
};
And the troublesome function is:
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
amt_count += 1;
temp[amt_count] = put_at_end;
value = temp;
}
The member function just seems to insert 0.0 instead of the user input, I have no idea why...
In main:
VectorDouble vec1(10);
double dd;
cout << "Enter 3 doubles to vec1:\n";
for(int i = 0; i < 3; i++)
{
cout << i << ": ";
cin >> dd;
vec1.push_back_vd(dd);
}
cout << "The variables you entered were:\n";
for(int i = 0; i < 3; i++)
cout << i << ": " << vec1.value_at(i) << endl;
I enter:
12.5
16.8
15.2
I get back:
0
0
0
I fixed it! Only problem is that the mistake was exceedinly simple. Sorry to waste everybodies time, but thanks to all, I did learn quite a lot!
The mistake was my placement of amt_count += 1;, I'm used to arrays indexed from 1 not zero (I have done a lot of coding in the R language). The corrected code with the memoery leak taken care of is:
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
temp[amt_count] = put_at_end;
amt_count += 1;
delete [] value;
value = temp;
}
This is what I understand about normal variables
All correct, with the caveat that I'd avoid the terminology "points to the value x"; you're pointing to the object, which in turn has value x.
This is what I essentially don't understand about arrays and pointers that point to arrays
You're confusing pointers with arrays. In int a[3], a is an array. It is not a pointer. It is an array.
*p3 = a isn't valid, so it means nothing.
p2 now points to p4, but what happens to the array p2 was pointing to?
You've leaked it.
// does this destroy the pointer and the array it is pointing to or just one or the other?
It destroys the thing you new'd, that the pointer is pointing to. i.e. the array
Otherwise all correct.
As for your vector implementation, the main problem is that temp[amt_count] is an overflow because you've already incremented amt_count. Also, vector implementations typically grow exponentially rather than on-demand. Finally, you're leaking the previous storage.
Using different terminology might help you:
A pointer is just an ordinary variable. Instead of holding an integer, a float, a double, etc., it holds a memory address. Consider the following:
int* p = nullptr; // p has the value "nullptr" or null memory address
int i = 5; // i has value 5
p = &i; // p now has the value of the address of i
The ampersand gets the address of a variable.
An asterisk dereferences a pointer; that is it will get the value stored in the memory address the pointer holds:
cout << *p << endl; // Prints whatever is stored in the memory address of i; 5
As for your vector implementation, try moving this line amt_count += 1; to below this line:
temp[amt_count] = put_at_end;, as you're trying to access beyond the end of your array.
Most of your understanding is correct. But...
a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
Although arrays and pointers can be indexed and treated in a similar fashion, they are different, and their differences can lead to some sneaky bugs; so be careful with this statement.
*p3 = a // what does this mean?
This is invalid. Your types don't match: *p3 is an integer, a is an array.
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
The array p2 was pointing to is now leaked memory. This is bad.
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?
The value of the pointer does not change. However, the memory it points to is deallocated, so dereferencing it will give you undefined results. It's best to set p2 = nullptr; after deleting it.
This answer might help with your understanding of arrays and accessing their elements.
"p2 now points to p4, but what happens to the array p2 was pointing to?"
It is 'leaked', this means its still allocated but there is no way to reach it anymore. If you keep doing this is the same program your memory size will keep growing
Other languages (Java, c#,...) have 'garbage collectors' that detect when this happens and will free the memory automatically
C++ solution to this problem is to never user naked arrays and pointers. Instead you use std::vector and std::shared_ptr; these will clean up for you
Your function is really wrong...
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
amt_count += 1;
temp[amt_count] = put_at_end;
value = temp;
}
Notice that in each call you allocate new array (even if there's still space), copy everything in it and leak memory (old array)...
Here is a slightly corrected version, but it's not guaranteed to be completely OK (;
void VectorDouble::push_back_vd(double put_at_end)
{
if(amt_count == max_count)
{
max_count += 1;
double *temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
delete[] value;
value = temp;
}
value[amt_count] = put_at_end;
amt_count += 1;
}

Having difficulty working with pointers

I having some issue when it comes to initializing pointers.
void findMM (int *PMM, int *theG)
{
// code I haven't written yet. It will essentially take two variables from //theG and store it in MM
}
int main()
{
int size;
int MM [2] = {1000, 0};
int *theG = NULL;
cout << "\nPlease insert size of array:" << endl;
cin >> size;
theG = new int [size];
findMM(&MM, &theG); //Get error with &MM
delete [] theG;
return 0;
}
The complier says that argument of type int (*)[2] is incompatible with parameter of type int ** So obviously that I have issue with the code in particular my (reference?) of array MM. Or perhaps there is other obvious faults that I am missing?
Edit attempt 2
void findMM (int *PMM, int *theG)
{
PMM [1] = 5;
theG [0] = 7;
}
int main()
{
int size;
int MM [2] = {1000, 0};
int *theG = NULL;
cout << "\nPlease insert size of array:" << endl;
cin >> size;
theG = new int [size];
findMM(MM, theG);
cout << MM [1] << endl << theG[0];
delete [] theG;
return 0;
}
The output would be 5 and 7 correct?
Since MM is an array, &MM is a pointer to an array (that's the type int (*)[2] that you see in the error). Instead, you seem to want to pass a pointer to the first element of the array. There are two ways to do that. Firstly, you can explicitly get the first element and then take the address of it: &MM[0]. Secondly, you can rely on array-to-pointer conversion to do it for you and just pass MM. Array-to-pointer conversion converts an array to a pointer to its first element.
I know this question has already been answered but I believe I can contribute to the asker's understanding.
Let's start with the basics:
void main()
{
int a = 2; // a is an int
cout << a << endl; // print 2
int *b; // b is a pointer-to-int
b = &a; // store the address of a in b
cout << *b << endl;// print the value that b points to, which is 2
int my_array = new int[3]; // allocate an array with 3 integers
my_array[0] = 50; // store 50 in the first element of the array
my_array[1] = 51; // store 51 in the second element of the array
my_array[2] = 52; // store 52 in the third element of the array
cout << c[0] << endl; // print 50
some_function(my_array, 3); // explained below
}
Now let's see how to pass arrays into functions. Assume we want to have a function called some_function that receives an array.
void some_function(int *some_array, int size_of_the_array)
{
// use the array however you like here
}
The function some_function receives a pointer to an int (also known as "pointer-to-int"). The name of an array is always the address of its first element, so if a function expects a pointer to an int and you give it the name of an array of ints, you are actually giving it the address of the first element in the array (this is just C++ syntax rules). So the function now has the address of the first element in the array, it can do stuff like *some_array to access the first element in the array, but what if it wants to access the other elements? It adds 1 to the pointer it already has and then applies the * operator to it: *(some_array + 1). Let's say an int is 4 bytes, if you add 1 to a pointer-to-int, the result of this addition is a new pointer that points to a location in memory 4 bytes ahead, so *(some_array + 93) is the value in the 94th element of the array some_array (array elements are stored sequentially in memory). A shorthand notation for this is some_array[93]. So if you have int *some_array = new int[100];, then some_array is a pointer and some_array[93] is the same as *(some_array + 93), which is the 94th element in the array.
The address itself though is not enough, you also need to know the number of entries in the array so that you don't try to access an element past the end of the array. In this example, assume that some_function simply prints the contents of the array, so if you don't provide 3 as the second argument to the function then it will have no way of knowing when to stop adding 1 to the pointer it received in the first argument. Beware, however, that by passing an array to a function this way, you are not passing the function a copy of the array, you are simply telling it where to find its contents in memory.

Copying one structure to another and Effect of changing one on Another

#include<stdio.h>
#include<string.h>
struct node
{
int a;
char *p;
};
int main()
{
struct node X,Y;
char s[5] = "Adam";
char t[5] = "Jack";
X.a = 5;
X.p = s;
Y = X;
Y.a = 10;
strcpy(Y.p,t);
printf("%d %s\n",X.a,X.p);
printf("%d %s\n",Y.a,Y.p);
return 0;
}
In this Question , Structure X has "a=5" and "P pointing to Adam". and then this is copied to another structure Y. and changes are made to Y.
But when strcpy(Y.p,t) is done .
OUTPUT IS :
5 Jack
10 Jack
This change is supposed to be only in Y , but these changes are also reflected for X. How so ?
MY question is "How does changing one structure member have effect on another when they are copied " ?
You initialized Y as copy of X. That means it contains the same pointer in the p field - you didn't ever change that.
When you do the strcpy, you're writing the contents of t overtop of s.
You're lucky you picked two 4-letter names...
strcpy(Y.p,t);
Y.p value is the same as the value of s. So the above function call is actually the same as:
strcpy(s, t);
This is because the character pointer p of both structures X and Y points to the same memory location.
so strcpy changes the data for both X and Y

How does this operation on pointers work?

int x = 4;
int* q = &x; // Is it always equivalent to int *q = &x; ?
cout << "q = " << q << endl; // output: q = 0xbfdded70
int i = *q; // A
int j = *(int*)q; // B, when is this necessary?
cout << "i = " << i << endl; // output: i = 4
cout << "j = " << j << endl; // output: j = 4
My question is what does lines A and B do, and why the outputs are both 4?
It is a basic usage of pointers, in A you dereference pointer (access the variable to which a pointer points)":
int i = *q; // A
while B is doing exactly the same but it additionally casts pointer to the same type. You could write it like that:
int j = *q; // B
there is no need for (int*)
int x = 4;
x is 4
int* q = &x;
q is the memory location of x (which holds 4)
cout << "q = " << q << endl; // output: q = 0xbfdded70
There's your memory location.
int i = *q; // A
i is the value at memory location q
int j = *(int*)q; // B
j is the value at memory location q. q is being cast to an int pointer, but that's what it already is.
int i = *q; // A
Dereferences a pointer to get the pointed value
int j = *(int*)q; // B
type casts the pointer to an int * and then dereferences it.
Both are same because the pointer is already pointing to an int. So typecasting to int * in second case is not needed at all.
Further derefenecing yields the pointed integer variable value in both cases.
Lines A and B are equivelent as q is already an int* and therefor (int*)q equals q.
int i = *q; yelds that i becomes the value of the integer pointed to by q. If you want to make i to be equal to the adress itself remove the asterisk.
A: Dereference - takes a pointer to a value (variable or object) and returns the value
B: Cast to int* and than dereference
The result is the same because the pointer is already to int. That's it.
Line A takes the value that q points to and assigns it to i. Line b casts q to the type int* (which is q's type already, so that cast is entirely redundant/pointless), then takes the value that q points to and assigns it to j.
Both give you 4 because that's the value that q points to.
Line A de-reference pointer q typed as int *, i.e. a pointer points to an int value.
Line B cast q as (int *) before de-reference, so line B is the same as int j = *q;.