Why won't this C pointer code work? - c

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.

Related

C read access violation - Pointers

I'm new to C and I'm getting a little tangled up with the Visual Studio Code.
I did not understand what that meant.
When I run the code in another compiler it does run.
void swap(int* x, int *y);
int exe1(int* num1Ptr, int* num2Ptr, int* num3Ptr);
int main()
{
int a = 123, b = 456 , c =4;
int* pa, * pb ,*pc;
pa = &a;
pb = &b;
pc = &c;
printf("pa = %d , pb = %d, pc = %d\n", *pa, *pb, *pc);
exe1(pa, pb, pc);
printf("pa = %d , pb = %d, pc = %d\n", *pa, *pb, *pc);
return 0;
}
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = *x;
}
int exe1(int* num1Ptr, int* num2Ptr, int* num3Ptr) {
if (*num2Ptr > *num1Ptr) {
swap(*num1Ptr, *num2Ptr);
}
if (*num3Ptr > *num2Ptr) {
swap(*num3Ptr, *num2Ptr);
}
if (*num3Ptr > *num1Ptr) {
swap(*num3Ptr, *num1Ptr);
}
}
Your swap routine expects two pointers to int and you pass two ints to it. Remove superfluous asterisks from the calls:
swap(*num1Ptr, *num2Ptr);
should read
swap(num1Ptr, num2Ptr);
Plus the mistake inside swap() which Kaitou points out in the answer.
"read access violation" occurs when we try to access a memory address which we don't have access to. In this case it is because of swap(*num1Ptr, *num2Ptr);
This function expects a pointer (relating to memory address) and should be called as swap(num1Ptr, num2Ptr);
*num1Ptr dereferences the pointer, it is now an integer value, not a pointer to a valid address. For example *num1Ptr can be 123 in the above code. Whatever sits at memory address 123 is probably used by system and we don't have read/write access to it. Debugger throws access violation.
The compiler should also print warnings.
The swap function needs a fix *y = temp; as noted earlier.
Unrelated to your question, exe1 compares values in this order
p1 & p2
p2 & p3
p1 & p3
If this were intended as a sort function for example, the third condition can negate the first condition. You may want to change the order of comparison as shown below:
void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void exe1(int* p1, int* p2, int* p3)
{
if (*p1 < *p2) swap(p1, p2);
if (*p1 < *p3) swap(p1, p3);
if (*p2 < *p3) swap(p2, p3);
}
int main()
{
int a, b, c;
a = 123, b = 456, c = 4;
exe1(&a, &b, &c); printf("%d, %d, %d\n", a, b, c);
a = 123, b = 456, c = 4000;
exe1(&a, &b, &c); printf("%d, %d, %d\n", a, b, c);
return 0;
}
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = *x; // this should be *y = temp;
}

Error in the program to find absolute difference in C

I want to calculate the sum and absolute difference of the two variable in this program.
#include <stdio.h>
#include <stdlib.h>
void update(int *a,int *b) {
// Complete this function
*a= *a+*b;
*b= abs(a-b);
}
int main() {
int a, b;
int *pa = &a, *pb = &b;
scanf("%d %d", &a, &b);
update(pa, pb);
printf("%d\n%d", a, b);
return 0;
}
But for some inputs this doesn't produce correct outputs for the absolute difference.eg.(4,5) produce correct outputs; (2,6) doesn't. I am unable to figure out the mistake. What is the reason?
As pointed out in other answer subtracting two pointers is UB.
To answer other part of problem,
Try to understand what is happening to the pointer values at each point of arithmetic operation,
void update(int *a,int *b) {
// Complete this function
*a= *a+*b; //<< here *a has sum of *a and *b
*b= abs(*a-*b);
//here *a itself is *a +*b
//so entire operation is abs(*a + *b -*b) and hence *b will have value of abs(*a)
}
Try to have local variables to keep intermediate values and assign it at the end,
void update(int *a,int *b) {
int sum = *a + *b;
int diff = abs (*a -*b);
*a= sum;
*b= diff;
}
*b= abs(a-b);
You are subtracting the pointers, which is undefined behavior because they don't point into the same array. You want to be subtracting the numbers they point to. Make this
*b= abs(*a-*b);

How can I swap two numbers by address?

#include<stdio.h>
void fun(int **a,int **b)
{
int **k;
k=a;
a=b;
b=k;
}
int main()
{
int a=3,b=6,*x=&a,*y=&b;
fun(&x,&y);
printf("%d %d",a,b);
return 0;
}
I swap the address,why it still outputs 3 6.
So what's the correct way to swap the two address?
p = ... never persists across the function call. Like everything else in C, if you want to change the caller's data, dereference the pointers you're given. k should be int *, and the assignments should be int *k = *a; *a = *b; *b = k;. that's it. Note also this changes nothing about the original a and b. All your swapping at this point are pointer values.
This code swaps two integers
#include<stdio.h>
void fun(int *a,int *b)
{
int k = *a;
*a = *b;
*b = k;
}
int main()
{
int a=3,b=6;
printf("%d %d\n",a,b);
fun(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
Output
3 6
6 3
Whereas, this code swaps two pointers. The integers they point to (a and b) remain as-is.
#include<stdio.h>
void fun(int **a,int **b)
{
int *k = *a;
*a = *b;
*b = k;
}
int main()
{
int a=3,b=6,*x=&a,*y=&b;
printf("%d %d\n",a,b);
printf("%d %d\n",*x,*y); // note using x and y with deref
fun(&x,&y);
printf("%d %d\n",a,b);
printf("%d %d\n",*x,*y); // note using x and y with deref
return 0;
}
Output
3 6
3 6
3 6
6 3
Lets make it clear from the first expression .
int a=3,b=6,*x=&a,*y=&b;
Now breaking it down .
int a = 3, b = 6
Here a and b are two memory locations . Say a is 10000000 and b is 10010000. So , after we write a = 3 , b = 6 the value 3 takes the place in memory location 10000000 and 6 in 10010000 . Now ,
*x=&a,*y=&b;
means , x is an integer pointer that has the address of integer variable a which is 10000000 and y has the address of b which is 10010000 . Note that , both x and y are also variable which can store the address as value of any integer variable . x and y has locations in memory let say 11000000 and 11011111. Now ,
fun(&x,&y);
You are passing the address of x and y to the function fun . It looks like fun(11000000, 11010000) .
Note that , you are not passing the address of a and b ! In function fun these addresses are in a ( pa for clarity ) and b (pb for clarity),
void fun(int **a,int **b)
{
int **k;
k = a;
a = b;
b = k;
}
Here , a(pa), b(pb) and k are pointers of pointer . They can hold the address of an integer pointer .a(pa) and b(pb) are holding the address of x and y respectively . Now when you swapping a(pa) and b(pb) you actually swapping the addresses ( of x and y ) in a(pa) and b(pb). So , after the function fun finishes it's execution a (pa) is pointing y and b(pb) is pointing x . In main function , nothing actually happened . When you do the following ,
void fun(int **a, int **b)
{
int *k;
k=*a;
*a = *b;
*b = k;
}
it swaps the address in x and y and they now pointing to b and a(in main function).
Now the final version comes ! If you would do the following , it actually make you happy ,
void fun(int **a, int **b)
{
int k;
k=**a;
**a = **b;
**b = k;
}
I hope you understand it . Happy coding !
Try this to swap the values to which *a and *b of fun() points
void fun(int **a, int **b)
{
int k;
k = **a;
**a = **b;
**b = k;
}
Instead of this:
int **k;
k=a;
a=b;
b=k;
you should have tried this:
int *k;
k=*a;
*a=*b;
*b=k;
And yeah, you should print *x and *y, because those are the variables you swap, not a and b.

Pointers in C , understanding the difference

void noOfClients(struct noOfClients *q );
I understand that a pointer's name holds the memory address of a variable.
But, when * comes with a pointer, it represents the content of that location.
In the above line of code, when passing a by reference, we'd say:
void noOfClients( &q);
But why?
Thank you.
* has different meaning when it is used in a variable/argument declaration and when it is used as a pointer dereference operator.
In a variable/argument declaration, it declares the variable/argument to be of a pointer type.
struct noOfClients *q
declares q to be a pointer to a struct noOfClients.
When used in an expression,
*q
dereferences where q points to.
PS
void noOfClients( &q);
is not the right way to call the function. Just use:
noOfClients(&q);
That will work if q is declared as an object.
struct noOfClients q;
noOfClients(&q);
void func(foo *a);
This is a function prototype of a function taking a pointer to a foo. Some people like to write this as
void func(foo* a);
There's no difference, but you might say that the function takes a "foo-pointer", rather than a "pointer to a foo".
a is a foo*
*a is a foo
There is no difference.
because & indicates the address of a particular variable and when you deal with functions so when you pass a variable to the function so you do some changes in that variable, sometimes the reflection of value are not done in that variable but if you pass a variable with its address then reflection will be done properly just try and understand following two codes it will sure help you
without &
#include <stdio.h>
void swap(int, int);
int main()
{
int x, y;
printf("Enter the value of x and y\n");
scanf("%d%d",&x,&y);
printf("Before Swapping\nx = %d\ny = %d\n", x, y);
swap(&x, &y);
printf("After Swapping\nx = %d\ny = %d\n", x, y);
return 0;
}
void swap(int a, int b)
{
int temp;
temp = b;
b = a;
a = temp;
}
with &
#include <stdio.h>
void swap(int*, int*);
int main()
{
int x, y;
printf("Enter the value of x and y\n");
scanf("%d%d",&x,&y);
printf("Before Swapping\nx = %d\ny = %d\n", x, y);
swap(&x, &y);
printf("After Swapping\nx = %d\ny = %d\n", x, y);
return 0;
}
void swap(int *a, int *b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}

Understanding pointers with a swap program in 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).

Resources