简体   繁体   中英

confusion in passing a pointer to function in C

I was trying to understand pointers in C and wrote this code

#include <stdio.h>

int swap(int *fa,int *fb){
    int temp = *fa;
    *fa = *fb;
    *fb = temp;
}

int main(){
    int a=5,b=7;

    int *pa = &a;
    int *pb = &b;

    swap(pa,pb);

    printf("%d\n",*pa);
    printf("%d\n",*pb);

    printf("%d\n",a);
    printf("%d",b);
}

now the output(as expected) is

7
5
7
5

I am having a bit of understanding of what is happening but I have a confusion that

  1. right after I call the swap function, this happens
fa = pa // fa points to what pa points to which means a
fb = pb // fb points to what pb points to which means b
  1. we swap values of fa and fb, which in turn swap values of a and b, since pa and pb points to a and b they now point to these new values.

IS THIS WHAT IS HAPPENING

Or is it that fa and fb effect pa and pb first, which in turn effect a and b.

  1. right after I call the swap function, this happens
fa = pa // fa points to what pa points to which means a
fb = pb // fb points to what pb points to which means b

If you mean after entering swap then yes. That is correct. Parameters are passed as a copy, which means inside that function fa and fb get a copy of pa and pb from the caller.

  1. we swap values of fa and fb, which in turn swap values of a and b, since pa and pb points to a and b they also point to these new values.

No. fa and fb are not touched at all. They are dereferenced. This means, the address where they point to, is affected. You can use printf to print the content of those pointer variables. They will not change. Instead the content of a and b are changed.

BTW: Your printf statements don't make much sense. You should print both before and after the function call to see any effect.

For starters pay attention to that your function swap having the return type int returns nothing.

int swap(int *fa,int *fb){

The return type int does not make a sense.

The function can be declared like

void swap(int *fa,int *fb);

The function swap does not swap the values of its arguments.

int swap(int *fa,int *fb){
    int temp = *fa;
    *fa = *fb;
    *fb = temp;
}

It swaps the pointed to by the arguments objects because within the function there are used expressions that dereference the pointers like

*fa or *fb .

Here is a demonstrative program that shows that the values of the pointers fa and fb are not changed.

#include <stdio.h>

void swap(int *fa,int *fb){
    printf( "fa = %p, fb = %p\n", ( void * )fa, ( void * )fb );
    int temp = *fa;
    *fa = *fb;
    *fb = temp;
    printf( "fa = %p, fb = %p\n", ( void * )fa, ( void * )fb );
}

int main(void) 
{
    int a=5,b=7;

    int *pa = &a;
    int *pb = &b;

    swap(pa,pb);
    
    return 0;
}

The program output might look like

fa = 0x7ffff85444f0, fb = 0x7ffff85444f4
fa = 0x7ffff85444f0, fb = 0x7ffff85444f4

As it is seen the pointers have the same values in the beginning and the end pf the function. It is the values of the pointed objects that are swapped.

And the pointers fa and fb do not affect the pointers pa and pb declared in main. Because the pointers fa and fb being local variables of the function get copies of the values stored in the pointers pa and pb .

When you pass the pointers to your function, you pass a variable which contains an address. When you dereference fa (or fb), you get the actual value at that address. So when you modify it, you modify the value for both pointers since they point to the same adress.

To understand pointers better you can go with actual fake addresses. Let's say that variable 'a' is stored at address 0x9000 in RAM and variable 'b' is stored at address 0x10000.

#include <stdio.h>

int swap(int *fa,int *fb){  //fa and fb are variables of type pointer which contain 0x9000 and 0x10000 respectively
    int temp = *fa;  //temp contains the content of address 0x9000 (a)
    *fa = *fb; //address 0x9000 contains content of address 0x10000 (b)
    *fb = temp; //address 0x10000 contains content of temp (a)
}

int main(){
    int a=5,b=7;

    int* pa = &a; //pa is a variable of type pointer which contains 0x9000
    int* pb = &b; //pb is a variable of type pointer which contains 0x10000

    swap(pa,pb);
}

Don't forget that int* is a variable of type pointer to an int. What it means is that the variable contains an address of a variable of type int. In reality it just points to memory. You could write something like

int* a = 0x9000;

You would have a pointer of type int which points to address 0x9000. That would be valid syntax but your OS would complain that you don't have access to that address. If you write

long* a = 0x9000;

The only difference is the amount of bytes you get when dereferencing. When you dereference a pointer you get the amount of bytes that the type contains. With the type int*, when you dereference you'll get 4 bytes (32 bits) starting at address 0x9000. With type long* you'll get 8 bytes (64 bits) starting at address 0x9000.

The size of a variable of type int* or long* is the same since this depends only on the architecture of you CPU. So with both of these you'll get a variable of type pointer which has the same size. The only difference is the amount of bytes you get when dereferencing.

we swap values of fa and fb, which in turn swap values of a and b, since pa and pb points to a and b they now point to these new values.

No - you swap the values of what fa and fb point to , which is a and b respectively. The values of fa and fb (along with pa and pb ) never change.

I modified your code as follows:

#include <stdio.h>
#include <stdlib.h>

void swap(int *fa,int *fb){
    printf( "Entering swap: fa = %p, fb = %p, *fa = %d, *fb = %d\n", (void *) fa, (void *) fb, *fa, *fb );
    int temp = *fa;
    *fa = *fb;
    *fb = temp;
    printf( "Leaving swap: fa = %p, fb = %p, *fa = %d, *fb = %d\n", (void *) fa, (void *) fb, *fa, *fb );
}

int main(){
    int a=5,b=7;

    int *pa = &a;
    int *pb = &b;

    printf( "Before swap: a = %d, b = %d, pa = %p, &a = %p, pb = %p, &b = %p, *pa = %d, *pb = %d\n", 
      a, b, (void *) pa, (void *) &a, (void *) pb, (void *) &b, *pa, *pb );

    swap(pa,pb);

    printf( "After swap: a = %d, b = %d, pa = %p, &a = %p, pb = %p, &b = %p, *pa = %d, *pb = %d\n", 
      a, b, (void *) pa, (void *) &a, (void *) pb, (void *) &b, *pa, *pb );

    return EXIT_SUCCESS;
}

When run, it gives the output 1 :

Before swap: a = 5, b = 7, pa = 0x7ffee8f43a60, &a = 0x7ffee8f43a60, pb = 0x7ffee8f43a5c, &b = 0x7ffee8f43a5c, *pa = 5, *pb = 7
Entering swap: fa = 0x7ffee8f43a60, fb = 0x7ffee8f43a5c, *fa = 5, *fb = 7
Leaving swap: fa = 0x7ffee8f43a60, fb = 0x7ffee8f43a5c, *fa = 7, *fb = 5
After swap: a = 7, b = 5, pa = 0x7ffee8f43a60, &a = 0x7ffee8f43a60, pb = 0x7ffee8f43a5c, &b = 0x7ffee8f43a5c, *pa = 7, *pb = 5

So, we can see the following are all true:

 fa ==  pa == &a
*fa == *pa ==  a == 5 // before swap, 7 after swap

 fb ==  pb == &b
*fb == *pb ==  b == 7 // before swap, 5 after swap

  1. The address values will likely change from run to run - the important thing is that fa and pa and &a are all the same value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM