Trying to understand a function to swap two int values - c

I know this function swaps two int values, but I'm trying to understand it
minutely what is *x=*y exactly doing.
1 void swap (int* x, int* y){
2 int temp = *x;
3 *x = *y;
4 *y = temp;
5 }
6
7 int x,y;
8 x = 1;
9 y = 2;
10 swap(&x,&y)
The function receives two addresses, where x and y lives, correspondingly.
An int variable, temp, is created and is assigned the value 1 from a dereferenced pointer to x.
The value 1 from a dereferenced pointer to x is assigned the value 2 from a dereferenced pointer to y. So, by *x = *y, I'm reading 1=2
Thanks a lot.

Let's try to explain *x = *y; without using the word "dereference":
*x represents the integer object pointed to by x. As it is the left operand of the assignment, it means that this integer object is going to be updated.
*y represents the integer object pointed to by y. As it is the right operand of the assignment, it means that the content of the integer object (i.e. its value) is going to be used.
*x=*y updates the integer object pointed to by x with the integer object pointed to by y.
Note: To clearly distinguish pointers from other types in the code, I suggest you to change naming as follows, using a prefix like p_ for pointer variables for example:
1 void swap (int* p_x, int* p_y){
2 int temp = *p_x;
3 *p_x = *p_y;
4 *p_y = temp;
5 }
6
7 int x,y;
8 x = 1;
9 y = 2;
10 swap(&x,&y)

When you assign something like int abc = 5; int *ptr = &abc; understand that :
ptr is an integer pointer
&abc is the address of the variable abc
ptr stores addresss of the variable abc
Writing *ptr is the equivalent to writing abc, and not same as writing 5 (a constant), although all three evaluates to 5 in an expression.
The * operator dereferences to give you the the variable , whose address is pointed to by ptr (i.e abc). Therefore it can be used as an lvalue(on the left side of an assignment).
Now in your example, when you tried the assignment x = *y you are trying to store the value pointed to by y ( which is an integer value) to x (which expects an address).
Now assume you somehow made the assignment, let us also assume that &y(i.e address of y ) is something like 1056(only for example sake) and value pointed to by y is something like 5. Then from now on x points to the address location 5 (which is not the actual address), thereby resulting in some garbage value.
Now an assignment like x = y would work flawlessly. But that would make the pointers x point to same location as pointed by y swap their pointing. That is if initially if x was pointing to variable a which was at address 1000 and y was pointing to a variable b which was at address 2000 , after the assignment valu of both x and y would be 1000. It only means that now we have two pointers to the variable b at address 2000, but has no impact on the actual variables.
Whereas writing *x = *y is equivalent to writing a = b
Hope this helped.

Here in swap(&x, &y); you are passing the addresses of variable x & y as arguments to the function swap(int* x, int* y).
As parameters of swap function are int pointers, the addresses of x and y are now stored in another int pointer type variables x and y.
NOTE:
x and y coincidently have the same name in both the functions but the x and y used in swap function are int pointers and the x and y used outside the swap function are int variables.
The value 1 from a dereferenced pointer to x is assigned the value 2 from a dereferenced pointer to y. So, by *x = *y, I'm reading 1=2
*x=*y is actually using an assignment operator with a left to right associativity. assignment operator assigns the value of right operand to the left operand.don't read it as 1=2, it will as it may prove to be problematic later.
I tried to make some assumptions. By *x = *y, I think *x is not dereferencing x, but is the adress of x, and this is getting assigned the value 2 of the dereferenced pointer to y.
*x=*y here, *x is the value of x and not the address of x and as described in point 3, this statement will assign the value of *y i.e. 2 to *x.
But why, instead of *x=*y, shouldn't it just be x=*y?
it shouldn't because x is an int pointer and *y is an int variable.

Related

How to evaluate double pointers in c?

I am learning c, and I am quite confused about this double pointer question.
int x = 44;
int *p = &x;
int **t = &p;
bool a = (*t = &x);
I need to tell whether a will be true or false, and the correct answer is true. My thoughts were that t points to the address of p, and p points to the address of x. I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p. Can anyone explain?
int x = 44;
Declares integer variable x, which stores value of 44.
int *p = &x;
Declares integer pointer variable called p, p now stores the address of x.
int **t = &p;
Declares pointer to pointer of type int called t, t stores the address of p. (Pointers have addresses too)
bool a = (*t = &x);
In C;
'*' = Extracts the value from an address (Dereference)
'&' = Gives address of variable (Reference)
Since t is a pointer to the value stored in p. *t will be the value stored in p, which is the address of x. (We figured this out in the second line)
On the other hand since the & is used on variable x. This will extract the address of x.
Therefore *t == &x, which sets the boolean value a to true.
I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p.
Well, that is both right and wrong. The "point to the address of" should read "designate" and it is right.
First of all, you declared 3 variables
int x = 42;
int *p = &x;
int **t = &p;
Now this could be read as x is an int, *p is an int and **t is an int. Then we initialize x to value 42, then p to address of x, and t to address of p.
Given
int *p = &x;
the two L-value expressions x and *p not only are both of type int, and have the same value; they designate the same object. Just like 10565305 and Amy Finck designate the same user. This is also called aliasing - *p aliases x, just like Amy Fink and User 10565305 are your aliases on Stack Overflow (and the name x is not the object itself, just like you're a person, not a name).
Likewise with int **t = &p, we now notice that just like above, *t and p designate the same object, p. And ps current value is that of expression &x. Hence *t == &x must be true.
As for *ts type, if **t is an int, then *t must be int * (the law of conservation of stars in pointers ;) which of course matches the type of p, and type of &x.
It will be true. Here is the explanation:
In bool a = (*t = &x); the variable t holds address of p. You are de-referencing t i.e *t will point to the content stored in location of p.
The content stored in address of p is address of x. Remember *p = &x. Comparing *t == &x will then be true.
In the question you have mentioned *t = &x, if that is the original code it is still true, as assignment in (*t = &x); returns a non-null pointer. When that non-null pointer is converted to a boolean, it becomes true.
The first line declares a variable 'x' of type 'int', and assigns the numeric literal value 44 to that variable.
int x = 44;
The next line (2) declares a variable 'p' of type 'pointer to int', and assigns the value of the expression '&x' (which is the address of x, a pointer to int),
int *p = &x;
The next line (3) declares a variable 't' of type 'pointer to, pointer to int' (a pointer that contains a pointer to an int type), and assigns the expression '&p' (which is the address of p, a pointer to int,
int **t = &p;
The variable t is a 'doubly-indirected pointer'.
Now comes the 'tricky part'.
The next line (4) declares a variable 'a' which is a bool(ean) variable (true/false), and assigns the value of the expression on the rhs (right hand side, '(*t = &x)'. The parenthesis are there to ensure the intended order of precedence is observed. So we evaluate the expression '*t = &x'.
bool a = (*t = &x);
Here is the 'tricky' part, the code provided has an assignment '=' operator! If this were comparison, then the '==' operator would appear. So this statement takes the address of x (pointer to int), and stores it into *t (the location pointed at by t, and that location is a pointer to int).
Were this comparison, the expression would compare the same values, and would be true. But this is assignment. And an assignment expression returns the value assigned, which is the address of x (pointer to x). On most systems, that pointer is a location in memory (and could only be zero(NULL) if the variable were stored at the zero address).
The expression is of type 'pointer to int', but is converted (cast) to type bool. Since C considers false=0 and true anything not equal to 0, the value is converted from (likely not NULL) pointer to int to bool (true).
Had the parenthesis been omitted, then the assignment would still occur (right to left order of evaluation for assignment operator), but then the cast would occur. But remove the parenthesis, compile it and see what your compiler says.
You said:
I need to tell whether a will be true or false, and the correct answer is true. My thoughts were that t points to the address of p, and p points to the address of x. I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p. Can anyone explain?
Here is my attempt an an explanation:
The bold part is where you are confused. **t == x == *p, and *t == &x == p.
**t references the value stored in at x's address, not the address itself.
*t =p references the address of x, and dereferencing either of them give you the value of x.
Does this explanation clear things up? I can expand or make a sample program if it helps.
sample scratch code would be to printf these values to gain clarity:
int x = 42; //&x = 0x1234DEAD (or some other address, just picked one for an example)
int * p = &x; // p = 0x1234DEAD and &p = 0x5678BEEF (agian an example address)
int **t = &p; // t = 0x5678BEEF
printf("%d and %d and %d\n",**t, *p, x); //should be 42;
printf("%p and %p\n",*t, p); //should be 0x1234DEAD;
printf("%p\n",t); //should be 0x5678BEEF;
My thoughts were that t points to the address of p
Yes.
and p points to the address of x
Yes.
I know if you put **t, it should point to the address of x
No, **t is x.
but I thought if you just put *t it should point to the address of p.
No, *t is p.
The dereference operator "gives you" the pointed-to thing. Hence, since, p is also &x (because that's what you set it to), *t == &x.
It's moot though because you didn't actually compare with ==, you assigned with =, so your expression evaluates to the result of that assignment, which is &x, which is a non-NULL pointer, so the whole thing is "true-like". (Only a null pointer converts to false).

Difference between returning address and returning pointer

#include <stdio.h>
#include <conio.h>
void main()
{
int m = 20;
int n = 30;
int *x = (int *)m;
int *y = (int *)n;
printf("%d", y-x); //Output is 5
}
How is the output 5? One of the reason could be that x and y consider 20 and 30 as address and during pointer arithmetic the value could be (30-20)/(size of int) which is 10/2 = 5.
My doubt is what is the difference between returning pointer and returning address ? Why the address of m was not stored in pointer variable x?
The behaviour of your program is undefined.
Pointer arithmetic - including the difference between two pointers - is only valid within arrays (including one past the end of the arrray), or between the address of a scalar and one past that.
The behaviour of your casts from an int to a pointer to an int is also undefined.
If you do have a valid difference between two pointers, then use the format specifier %td to output it.
The address of m wasn't stored in x because you didn't assign it the address of m. You assigned it the value of m. The cast you applied masked the fact that you attempted to assign an integer to a pointer, which the compiler would have warned you about.
If you want to use the address of a variable, use the address-of operator &:
int *x=&m;
int *y=&n;
You are correct regarding why the output is 5. The values of m and n are assigned to pointers and are thus treated as addresses.
Note however that pointer subtraction is undefined unless both operands point to members of the same array (or one past the end of that array). Also note that it is undefined behavior to print pointers with the %d format specifier. You need to use %p instead, and you need to cast the given parameter to void * (one of the rare cases where a cast to/from void * is required).
if you want to store the adress of m in x simply do int* x = &m;
the casting to int type pointer here is causing the problem in my optinion.
also if you want to calculate the values of y-x then do *y-*x. as it is in your code you calculate the adress of n - the adress of m.
You have to use %p if you would like to show the address that is stored in a pointer. In your code, you should use * before the name of the pointer.
#include<stdio.h>
int main()
{
int m=20; int n=30;
int *x= &m;
int *y= &n;
printf("\n%d", (*y)-(*x)); //Output is 10
printf("\n%p address of m", x);
printf("\n%p address of n", y);
return 0;
}
int *x=(int *)m;
int *y=(int *)n;
By doing this what you would be doing is -
in a pointer x - you put the value m ( Treat this as a pointer as well as you are doing int *.
Hence x would have a value of 20 ( 0x14 ) and y would have a value of 30 ( 0x1E).
Pointer arithmetic is bit different from normal arithmetic operation
https://www.tutorialspoint.com/cprogramming/c_pointer_arithmetic.htm
And about assigning address you should use a &variable to do that

What is the difference between "*x = 1" and "x = 1" in C?

I'm very new to C. I come from a Java background, and I'm having a hard time understanding pointers. My understanding of what *x = 1 is take the memory address of x and assign it to 1, where as x = 1 means assign the variable x to the value 1.
Am I correct?
Well, as written you have it completely backwards, since you're saying assign x to the value 1 etc.
x=1 means store the value 1 to the variable x.
*x=1 means store the value 1 at the memory address x points to.
*x = 1;
means that x contains a memory address, assign 1 to that memory address.
x = 1;
means assign 1 to the variable x.
x = VARIABLE
*x = POINTER TO ADDRESS
By saying x=1 means you are directly assigning the value 1 into the x. Where as *x=1 has a bit different approach.
Say, int y = 10 and x is a pointer which is pointing to the address of y by defining int *x = &y. After declaration of *x, through out the program, *x will be treated as the value at the address of y. So, when *x=1 is used, the the value at the address of y, which was 10 earlier, will be changed to 1 now. Thus, y=1 and *x=1 are internally doing same thing.
You can follow this link for detailed understanding in simpler way about C pointers.

Why can't a c pointer be treated as an array?

In the question Find size of array without using sizeof in C the asker treats an int array like an array of int arrays by taking the address and then specifying an array index of 1:
int arr[100];
printf ("%d\n", (&arr)[1] - arr);
The value ends up being the address of the first element in the "next" array of 100 elements after arr. When I try this similar code it doesn't seem to do the same thing:
int *y = NULL;
printf("y = %d\n", y);
printf("(&y)[0] = %d\n", (&y)[0]);
printf("(&y)[1] = %d\n", (&y)[1]);
I end up getting:
y = 1552652636
(&y)[0] = 1552652636
(&y)[1] = 0
Why isn't (&y)[1] the address of the "next" pointer to an int after y?
Here:
printf("(&y)[1] = %d\n", (&y)[1]);
You say first: take address of y. Then afterwards you say: add 1 times so many bytes as the size of the thing which is pointed to - which is pointer to int, and hence probably 4 bytes are added - and dereference whatever is that on that address. But you don't know what is on that new memory address and you can't/shouldn't access that.
Arrays are not pointers, and pointers are not arrays.
The "array size" code calculates the distance between two arrays, which will be the size of an array.
Your code attempts to calculate the distance between two pointers, which should be the size of a pointer.
I believe the source of confusion is that (&y)[1] is the value of the "next" pointer to an int after y, not its address.
Its address is &y + 1.
In the same way, the address of y is &y, and (&y)[0] - or, equivalently *(&y) - is y's value.
(In the "array size" code, (&arr)[1] is also the "next" value, but since this value is an array, it gets implicitly converted to a pointer to the array's first element — &((&array)[1])[0].)
If you run this:
int *y = NULL;
printf("y = %p\n", y);
printf("&y = %p\n", &y + 0);
printf("&y + 1 = %p\n", &y + 1);
the output looks somewhat like this:
y = (nil)
&y = 0xbf86718c
&y + 1 = 0xbf867190
and 0xbf867190 - 0xbf86718c = 4, which makes sense with 32-bit pointers.
Accessing (&y)[1] (i.e. *(&y + 1)) is undefined and probably results in some random garbage.
Thanks for the answers, I think the simplest way to answer the question is to understand what the value of each expression is. First we must know the type, then we can determine the value
I used the c compiler to generate a warning by assigning the values to the wrong type (a char) so I could see exactly what it thinks the types are.
Given the declaration int arr[100], the type of (&arr)[1] is int [100].
Given the declaration int *ptr, the type of (&ptr)[1] is int *.
The value of a int[100] is the constant memory address of where the array starts. I don't know all the history of why that is exactly.
The value of a int * on the other hand is whatever memory address that pointer happens to be holding at the time.
So they are very different things. To get the constant memory address of where a pointer starts you must dereference it. So &(&ptr)[1] is int ** which the constant memory address of where the int pointer starts.

What is the difference between *x=i and x=&i

What is the difference between *x=i and x=&i?
Code:
int i=2;
int *x;
*x=i; //what is the difference between this...
x=&i; //...and this??
//Also, what happens when I do these? Not really important but curious.
x=i;
*x=*i;
*x=i; //what is the difference between this...
This assigns the value of i to an integer stored at the address pointed to by x
x=&i; //...and this??
This assigns the address of i to x.
Note that in your example x is unassigned, so the behavior of *x=i is undefined.
Here is a better illustration:
int i = 2, j = 5;
printf("%d %d\n", i, j); // Prints 2 5
int *x = &j;
*x = i;
printf("%d %d\n", i, j); // Prints 2 2
int i=2;
int *x;
*x=i; // x is not initialized, this is undefined behavior
x=&i; // this assigns the address of i to x
and
*x=&i; // is invalid C. You cannot assign a pointer to an
// integer without an explicit conversion.
*x=i changes the value stored in the memory location pointed to by x to be equal to the value stored in i.
x=&i changes the memory location x is pointing to to i's memory location.
x=i is wrong. You will most likely get a segfault.
*x=*i is wrong. You cannot dereference i, because i is not a pointer.
*x=&i (actually, more properly, *x=(int)&i) will store the memory location of i as an integer in the memory location pointed to by x.
*x=i; dereferences the pointer x and assigns i.
x=&i makes the pointer x point at the variable i.
*x = i changes the value stored at the address which is stored in x. In your case, unedited, that will crash, because the address x is likely junk, possibly NULL. You would need a malloc() or new or something.
x = &i changes the address stored in x, so that is is the address of the variable i. This is perfectly safe in your example.
Well, when you say
*x = i
You're saying: make the variable x points to the value i.
When you say
x = &i
You're saying make the address x points to the address of i.
And I guess you should be able to figure the other ones out by yourself!
*x = i
This actually assigns the value of i to the memory location pointed to by x.
x = &i
This assigns the address of variable i to a pointer variable x. x should be a pointer.
When you do x = i, this will give you a runtime error, as you are trying to erroneously assign an address(which in this case is 2) which does not belong to the address space of your process. To successfully do this, i should also be a pointer and must point to an address which is in your address space.
When you do *x = *i, in your case will again give an error. If i is a pointer, then the address pointed to by x will get the value present at the address pointed to by i.
*x = i assigns 2 to the memory address pointed to by x. Note that this would probably crash because x hasn't been initialized to a memory address via malloc or an assignment to a buffer or address of a stack variable.
x = &i assigns the pointer x to the address of variable i.
x = i would assign the pointer x to the value of 2, which would most likely point to an invalid memory address and would require a cast.
*x = *i would depend on the current value of x. And since i is not a pointer you cannot dereference it.
*x = &i would write the address of i to the memory address pointed to by x, which would depend on the code preceding it. It would likely crash if you didn't assign x to a valid address.
Some of these calls would require a cast to be syntactically correct.

Resources