Understanding pointers with a swap program in C - c

I am trying to better understand pointers and referencing in C, and my course provided the following program as an example.
#include <stdio.h>
void swap(int* a, int* b);
int main(void)
{
int x = 1;
int y = 2;
swap(&x, &y);
printf("x is %i\n", x);
printf("y is %i\n", y);
}
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
I shambled together the following to see if it would help me understand better what's happening, mainly in regards to the need to use & versus *(dereference). Basically, the syntax of declaring a pointer to int type (int* a) versus using an asterisk to "dereference" (*a = *b) is quite confusing to me, and I was hoping someone could enlighten me. Here's another version of the above that I thought would help clarify, but really doesn't:
#include <stdio.h>
void swap(int* a, int* b);
int main(void)
{
int x = 1;
int y = 2;
int *a = &x;
int *b = &y;
swap(a, b);
printf("x is %i\n", x);
printf("y is %i\n", y);
}
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
In short, my question is, is there a functional difference between what these two programs are doing? What is the difference between a dereference (*a = *b) versus using the & operator (*a = &x)".

You're confusing declaration and assignment.
*a = *bis called assignment. Notice it does not include a type name.
int *a = &x on the other hand is called declaration. Notice that you initialize the pointer with the address of x. You are not dereferencing the pointer, but are declaring it as a pointer to int.
Look at this:
int main() {
int a = 5;
int b = 2;
int *c = &a; // c when dereferenced equals 5; **Declaration**
int *d = &b; // d when dereferenced equals 2; **Declaration**
int tmp = *c; // tmp equals 5
*c = *d; // c when dereferenced now equals 2 **Assignment**
*d = tmp; // d when dereferenced now equals 5 **Assignment**
return 0;
}
Finally, when you declare and initialize a pointer in the same statement, you assign the pointer the address of what you want to have point at it. When you want to change the value the object points to, you dereference it using *. On the other hand, if you want to change what it points to, you do not dereference it.

&xreturns the address of x. x is of type integer and a is of type pointer to integer. In this case, (*a = &x), you are assigning the address of x to a variable of type "pointer to integer", which is a. (*a = *b) is a assign operation between two variables of the same type which is integer. I said integer because even though a and b are "pointers to integers", in that operation they are dereferenced and therefore the integer value to which these are pointed to is read.
The confusion I think you have is because (*a = &x) only makes sense during a pointer initialization.

If you set *a = *b since a and b are pointer variables, the * operator will retrieve the value of a cell in memory that b points to it and puts it to the cell that a points to it.
For *a = &x, the & operator finds the address of the cell that allocated to the x variable, and puts it in the cell that a points to it.

In short, my question is, is there a functional difference between
what these two programs are doing?
No, the functional effect is exactly the same. In
int *a = &x;
int *b = &y;
swap(a, b);
// swap(&a, &b)
The type of a is the same of &a, namely int* (pointer to int). The only difference is that you're using other variables to store that, which is not really needed logically but it is absolutely fine to have it, especially if it could help you understand the syntax.
What is the difference between a dereference (*a = *b) versus using &
(*a = &x).
*a = *b assigns the value pointed to by b (obtained with *b) in the ones pointed to by a. To see it more clearly,
int tmp = *b;
*a = tmp;
&(*a = &x) is not a valid expression because you can't store an address into an int (actually you can, but that's beyond the point).

Related

Swapping two integers using pointers using c

I am trying to swap the value of two integers using pointers, see code below: swapping number using pointer in c:
{
int a = 10;
int b = 20;
swapr(&a, &b);
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
void swapr(int *x, int *y) //function
{
int t;
t=*x;
*x=*y;
*y=t;
}
In the code why is swap(&A, &B); used when *x and *y point to a value not an address
When you say (int *x, int *y) you're just declaring x and y as pointers. In all future usages, when you say x, it means the pointer and when you say *x, it means the value it points to.
In a declaration, the * in the declarator indicates that the object has pointer type. Take the declaration
int *p;
The type of p is "pointer to int". This type is specified by the combination of the type specifier int and the declarator *p.
Pointer-ness, array-ness, and function-ness are all specified as part of the declarator:
T *p; // p is a pointer to T
T a[N]; // a is an N-element array of T
T f(); // f is a function returning T
T *ap[N]; // ap is an array of pointers to T
T (*pa)[N]; // pa is a pointer to an array of T
T *fp(); // fp is a function returning pointer to T
T (*pf)(); // pf is a pointer to a function returning T
etc.
In C, declaration mimics use - if you have a pointer to an int named p and you want to access the value it points to, you dereference it with the * operator, like so:
x = *p;
The expression *p has type int, so the declaration of p is
int *p;
In main, the expressions &a and &b have type int *, so the corresponding parameters have to be declared as int *.
x == &a // int * == int *
y == &b // int * == int *
*x == a // int == int
*y == b // int == int
Basically the way var declarations work is if you declare a variable
int c;
You've just declared an integer and you can assign values to it or retrieve its value like this
int a;
int b;
a = 10; // assign 10
b = a; //assign value of a to b
Pointers are a bit different though. If you declare a pointer and you want to assign a value to it then you must dereference it with the * operator
int * a; // declare a pointer
int b; // declare a var
b = 10; // assign 10 to b
*a = b; // assign 10 as the value of a
b = 20; // b is now 20 but the var a remains 10
But you can also assign a pointer to point at a memory address
int * a;
int b;
b = 10; // assign 10 to b
a = &b; // assign address of b to a (a points at b)
b = 20; // value of b changes (thus value of a is also 20 since it is pointing at b
So if you have a function signature
int func (int * a, int * b);
All this is means is that the function takes the address of two variable
int a;
int b;
int * x;
int * y;
func(&a, &b); // send it the address of a and b
func(x, y); // send it the address of x and y
func(x, &b);
Basically a normal var's address can be accessed with the & operator.

Confusion when Swapping Pointers

In Dennis M Richies book "C programming language" it talks about pointers, and one of the examples is swapping two pointers:
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp
}
What's confusing me slightly is *a = *b. If b is already a pointer being passed in, why does it need to be dereferenced before assigning it to *a? Why wouldn't a = b work as their both pointers already?
a = b means you are assigning address of b to a which not the right way.
for swapping two numbers means you need to get value at that address and that value you have to swap.
so right way is to do *a = *b; i.e value at the address of b assigned to value at the address of a.
On doing a = b, both a and b will point to location pointed by b, this will defeat the purpose of passing a and b as reference; as the swap() will not be reflected after the function returns.
*ptr is dereferencing of the pointer.
*a = *b; means you are putting in the value contained at location b into the location where a points to. And this is what is required in the swap function.
a = b; means you are assigning value of pointer b to pointer a. This is not what you need in swap logic.
The reason for the confusing is that the function actually does not swap pointers.
Let's at first assume that the function has to swap pointers and its implementation has to be look as you think
void swap(int *a, int *b)
{
int *temp;
temp = a;
a = b;
b = temp
}
The function can be called the following way
int x = 10;
int y = 20;
int *px = &x;
int *py = &y;
swap( px, py );
Parameters of a function are its local variables that are initialized by arguments. So the function call can look the following way
void swap(/*int *a, int *b*/)
{
int *a = px;
int *b = py;
int *temp;
temp = a;
a = b;
b = temp
}
Within the function these local variables were swapped but the original arguments were not changed. Local variables a and b got copies of values stored in px and py. Thus after exiting the function these local variables will be destroyed and at the same time px and py will not be changed.
To change the pointers the function should look the following way
void swap(int **a, int **b)
{
int *temp;
temp = *a;
*a = *b;
*b = temp
}
In this case the function swaps values pointed to by pointers int **a and int **b and these values are values stored in px and py. Of course the function must be called like
swap( &px, &py );
Now let's return to the original function
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp
}
It is similar to the function that swaps pointers. However in this case it swaps objects pointed to by int *a and int *b.

C function with pointers work on one computer, and doesn't work on another

#include <stdio.h>
void swap (int *a, int *b)
{
int *tmp;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
}
I'm using codeblocks, and this code won't work, and I don't understand why... On one computer it works perfectly but on the other it won't run at all.
Any help?
Thanks in advance.
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
What you need is a variable tmp to store the value and not a pointer *tmp.
The below code really a poor way of doing this but
int *tmp = malloc(sizeof(int));
*tmp = *a;
*a = *b;
*b = *tmp;
Once done please free the memory using
free(tmp);
Gopi already corrected your code - adding on to the previous answer - i think this is good to know information for a newbie:
Section 4.1 states:
An lvalue (3.10) of a
non-function, non-array type T can be
converted to an rvalue. If T is an
incomplete type, a program that
necessitates this conversion is
ill-formed. If the object to which the
lvalue refers is not an object of type
T and is not an object of a type
derived from T, or if the object is
uninitialized, a program that
necessitates this conversion has
undefined behavior. If T is a
non-class type, the type of the rvalue
is the cv-unqualified version of T.
Otherwise, the type of the rvalue is
T.
When you try to dereference and uninitialized pointer the behavior is undefined. Undefined means anything can happen - there is no guarantee. So you can get different behavior in different environments.
From Wiki Making pointers safer
A pointer which does not have any address assigned to it is called a wild pointer. Any attempt to use such uninitialized pointers can cause unexpected behavior, either because the initial value is not a valid address, or because using it may damage other parts of the program. The result is often a segmentation fault, storage violation or wild branch (if used as a function pointer or branch address).
What you did here:
int *tmp;
*tmp = *a;
is that you created a pointer to int which is not pointing to anything - basically it contains some junk value (could be your pincode even - who knows).
Your mistake was to use uninitialized memory. Always allocate memory to a pointer before using it. Next, don't forget to free the allocated memory after you're done with it.
Also, you should add return 0; at the end of your main() function.
If you don't mind a second opinion, check the below code.
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b)
{
int *tmp = malloc(sizeof(*tmp));
*tmp = *a;
*a = *b;
*b = *tmp;
free(tmp);
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
return 0;
}
If you want to use pointers, although it does not make any sense at all
void swap(int *a, int *b)
{
int tmp[1];
*tmp = *a;
*a = *b;
*b = *tmp;
}
here tmp is not strictly a pointer, but you can use the * indirection operator on it.
Or
void swap(int *a, int *b)
{
int value = *a;
int *tmp = &value;
*tmp = *a;
*a = *b;
*b = *tmp;
}
Or you can use malloc as Gopi already pointed out.
If you want to use pointers, then do use pointers:
#include <stdio.h>
void swap (int ** ppx, int ** ppy)
{
int * p = *ppx;
*ppx = *ppy;
*ppy = p;
}
int main (void)
{
int x = 5;
int y = 7;
int * px = &x;
int * py = &y;
printf ("\nx = %d\ny = %d\n", *px, *py);
swap (&px, &py);
printf ("\nx = %d\ny = %d\n", *px, *py);
return 0;
}
Result:
x = 5
y = 7
x = 7
y = 5

Change value of variable with a pointer?

I am new with pointers and I am trying to create a function that changes value of variable a to variable b, and the value of variable b to variable a.
I think I have everything right except the function. In the function I am trying to make the value of pointer a (*a) and assign it to the value pointer b has, and vice verca. However my output is "a is now y and b is now y".
Is this because when I assign *a to b, b will get *a's value which just changed to an y?
#include <stdio.h>
void change(char* a, char* b)
{
*a = b;
*b = a;
}
int main(void)
{
char a = 'x';
char b = 'y';
printf("a is now %c and b is now %c\n", a, b);
change(&a, &b);
printf("a is now %c and b is now %c\n", a, b);
return 0;
}
Your change function is wrong:
void change(char* a, char* b)
{
char temp = *a;
*a = *b;
*b = temp;
}
First make a temporary variable - copy it in a temp variable, then swap the value. This line is UB:
*a = b;
*b = a;
You are trying to store a pointer's value in a char.
Yes, your first assignment overwrites the value that is needed in the second one.
The solution is to use some temporary storage to hold the one of the variable values during the swap:
void change(char *a, char *b)
{
const char old_a = *a;
*a = *b;
*b = old_a;
}
There is also a trick you can do to go around this (using bitwise XOR), but it's scary so ignore it at this point.

Why won't this C pointer code work?

Complete C newb here. Trying to learn/understand pointers by messing with simple code fragments.
#include <stdio.h>
void swap(int *px, int *py)
{
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
main()
{
int *a, *b;
*a = 1;
*b = 2;
swap(&a,&b);
printf("%d %d\n", *a, *b);
}
Why is this not valid? The code works when I remove the dereferencing operator * from main.
Conceptually, this seems like it should work. I initialize a and b as pointers which point to int 1 and int 2, respectively. I then send their addresses to swap(), which should switch what they point to.
There are a couple of problems. First, the pointers a and b are not pointing to valid memory. So the assignment of the integer values is undefined (possible crash). Secondly, the call to swap (assuming a and b are pointing to valid memory) should not include the address (it is currently sending the address of the pointer variable).
The following changes would make it work:
int a, b;
a = 1;
b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
The swap() function is OK but inside main you are taking the addresses of pointers, so you're passing int** arguments to int* parameters.
int *a, *b;
swap(&a,&b);
To fix it, replace the code in main() with :
int a = 1, b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
Pointers point to data. A pointer itself doesn't comprise memory for storage, it just points to existing memory. So when you declare int *a; , you just have a garbage pointer with no useable value, and you mustn't dereference it.
The only sensible way to use pointers is to assign them the address-of something (or the result of some allocation function):
int i;
int *a = &i; // now a points to i
Therefore, the right way to use your swap function is to pass it addresses of integers:
int i = 10;
int j = -2;
swap(&i, &j);
a and b are uninitialized pointers, dereferencing them induces undefined behavior. You want:
int main() {
int a, b;
a = 1;
b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
return 0;
}
Your method signature is wrong. You ask for two pointers to int, yet you pass in two pointers to pointers to int.
When you say, " I then send their addresses to swap(), which should switch what they point to." Are you trying to change the address values within the pointer variables in main, to switch which bit of memory they are pointing to? In that case you will need another step of redirection:
#include <stdio.h>
void swap(int **px, int **py) {
int *tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
int main (void) {
int x, y; /* storage to point to */
int *a, *b;
a = &x;
b = &y;
*a = 1;
*b = 2;
printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
swap(&a, &b);
printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
}
$ ./a.out
(*a, *b, x, y) == (1, 2, 1, 2)
(*a, *b, x, y) == (2, 1, 1, 2)
The x & y values have not changed, but a was pointing to x and now points to y and vice versa for b.

Resources