简体   繁体   English

在 C 中传递指向函数的指针时的混淆

[英]confusion in passing a pointer to function in C

I was trying to understand pointers in C and wrote this code我试图理解 C 中的指针并编写了这段代码

#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.我们交换 fa 和 fb 的值,然后交换 a 和 b 的值,因为 pa 和 pb 指向 a 和 b,它们现在指向这些新值。

IS THIS WHAT IS HAPPENING这是正在发生的事情吗

Or is it that fa and fb effect pa and pb first, which in turn effect a and b.或者是 fa 和 fb 首先影响 pa 和 pb,依次影响 a 和 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.如果您的意思是在进入swap之后,那么是。 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.参数作为副本传递,这意味着在函数fafb内部从调用者那里获取papb的副本。

  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.我们交换 fa 和 fb 的值,然后交换 a 和 b 的值,因为 pa 和 pb 指向 a 和 b,它们也指向这些新值。

No. fa and fb are not touched at all.fafb根本没有接触。 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.您可以使用printf打印这些指针变量的内容。 They will not change.他们不会改变。 Instead the content of a and b are changed.而是更改了ab的内容。

BTW: Your printf statements don't make much sense.顺便说一句:你的printf语句没有多大意义。 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 swap(int *fa,int *fb){

The return type int does not make a sense.返回类型int没有意义。

The function can be declared like该函数可以声明为

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

The function swap does not swap the values of its arguments.函数 swap 不交换其参数的值。

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 . *fa*fb

Here is a demonstrative program that shows that the values of the pointers fa and fb are not changed.这是一个演示程序,它表明指针fafb的值没有改变。

#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.并且指针fafb不影响 main 中声明的指针papb Because the pointers fa and fb being local variables of the function get copies of the values stored in the pointers pa and pb .因为作为函数局部变量的指针fafb获得了存储在指针papb中的值的副本。

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.当您取消引用 fa(或 fb)时,您将获得该地址的实际值。 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.假设变量“a”存储在 RAM 中的地址 0x9000,变量“b”存储在地址 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.不要忘记 int* 是一个指向 int 的指针类型的变量。 What it means is that the variable contains an address of a variable of type int.这意味着该变量包含一个 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.您将有一个 int 类型的指针指向地址 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.对于 int* 类型,当您取消引用时,您将获得从地址 0x9000 开始的 4 个字节(32 位)。 With type long* you'll get 8 bytes (64 bits) starting at address 0x9000.使用 long* 类型,您将获得从地址 0x9000 开始的 8 个字节(64 位)。

The size of a variable of type int* or long* is the same since this depends only on the architecture of you CPU. int* 或 long* 类型变量的大小是相同的,因为这仅取决于 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.我们交换 fa 和 fb 的值,然后交换 a 和 b 的值,因为 pa 和 pb 指向 a 和 b,它们现在指向这些新值。

No - you swap the values of what fa and fb point to , which is a and b respectively.不 - 你交换fafb指向的值,分别是ab The values of fa and fb (along with pa and pb ) never change. fafb的值(以及papb )永远不会改变。

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 :运行时,它给出输出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.地址值可能会随着运行而变化 - 重要的是fapa以及&a都是相同的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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