在 C 中传递指向函数的指针的混淆
confusion in passing a pointer to function in C
我试图理解 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);
}
现在输出(如预期)是
7
5
7
5
我对正在发生的事情有了一些了解,但我有一个困惑
- 在我调用交换函数后,就发生了这种情况
fa = pa // fa points to what pa points to which means a
fb = pb // fb points to what pb points to which means b
- 我们交换 fa 和 fb 的值,进而交换 a 和 b 的值,因为 pa 和 pb 指向 a 和 b,它们现在指向这些新值。
这是怎么回事
或者是fa和fb先影响pa和pb,再影响a和b
对于初学者,请注意您的函数 swap
具有 return 类型 int
return 什么都没有。
int swap(int *fa,int *fb){
return 类型 int
没有意义。
函数可以这样声明
void swap(int *fa,int *fb);
函数 swap 不交换其参数的值。
int swap(int *fa,int *fb){
int temp = *fa;
*fa = *fb;
*fb = temp;
}
它交换参数对象指向的指针,因为在函数中使用了取消引用指针的表达式,例如
*fa
或 *fb
.
这是一个演示程序,显示指针 fa
和 fb
的值没有改变。
#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;
}
程序输出可能看起来像
fa = 0x7ffff85444f0, fb = 0x7ffff85444f4
fa = 0x7ffff85444f0, fb = 0x7ffff85444f4
正如所见,指针在函数的开头和结尾具有相同的值。交换的是指向对象的值。
并且指针fa
和fb
不影响main中声明的指针pa
和pb
。因为指针 fa
和 fb
作为函数的局部变量获取存储在指针 pa
和 pb
.
中的值的副本
- 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
如果你的意思是在输入 swap
之后,那么是的。那是对的。参数作为副本传递,这意味着在该函数内部 fa
和 fb
从调用者那里获得 pa
和 pb
的副本。
- 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
根本没动过。它们被取消引用。这意味着,它们指向的地址受到影响。您可以使用 printf
打印那些指针变量的内容。他们不会改变。
相反,a
和 b
的内容已更改。
顺便说一句:您的 printf
陈述没有多大意义。您应该在函数调用之前和之后打印以查看效果。
当您将指针传递给您的函数时,您传递的是一个包含地址的变量。当您取消引用 fa(或 fb)时,您将获得该地址的实际值。所以当你修改它时,你修改了两个指针的值,因为它们指向同一个地址。
要更好地理解指针,您可以使用实际的假地址。假设变量 '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);
}
不要忘记 int* 是一个指向 int 的指针类型的变量。它的意思是该变量包含一个int类型变量的地址。实际上它只是指向内存。你可以这样写
int* a = 0x9000;
你会有一个指向地址 0x9000 的 int 类型的指针。那将是有效的语法,但您的 OS 会抱怨您无权访问该地址。如果你写
long* a = 0x9000;
唯一的区别是取消引用时获得的字节数。当你取消引用一个指针时,你会得到该类型包含的字节数。对于 int* 类型,当您取消引用时,您将获得从地址 0x9000 开始的 4 个字节(32 位)。使用 long* 类型,您将获得从地址 0x9000 开始的 8 个字节(64 位)。
int* 或 long* 类型变量的大小是相同的,因为这仅取决于您的架构 CPU。因此,对于这两者,您将获得一个具有相同大小的指针类型变量。唯一的区别是取消引用时获得的字节数。
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
分别。 fa
和 fb
(以及 pa
和 pb
)的值永远不会改变。
我修改了你的代码如下:
#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;
}
当运行时,它给出输出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
所以,我们可以看到以下都是正确的:
fa == pa == &a
*fa == *pa == a == 5 // before swap, 7 after swap
fb == pb == &b
*fb == *pb == b == 7 // before swap, 5 after swap
- 地址值可能会从 运行 变为 运行 - 重要的是
fa
和 pa
以及 &a
都是 相同 值。
我试图理解 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);
}
现在输出(如预期)是
7
5
7
5
我对正在发生的事情有了一些了解,但我有一个困惑
- 在我调用交换函数后,就发生了这种情况
fa = pa // fa points to what pa points to which means a
fb = pb // fb points to what pb points to which means b
- 我们交换 fa 和 fb 的值,进而交换 a 和 b 的值,因为 pa 和 pb 指向 a 和 b,它们现在指向这些新值。
这是怎么回事
或者是fa和fb先影响pa和pb,再影响a和b
对于初学者,请注意您的函数 swap
具有 return 类型 int
return 什么都没有。
int swap(int *fa,int *fb){
return 类型 int
没有意义。
函数可以这样声明
void swap(int *fa,int *fb);
函数 swap 不交换其参数的值。
int swap(int *fa,int *fb){
int temp = *fa;
*fa = *fb;
*fb = temp;
}
它交换参数对象指向的指针,因为在函数中使用了取消引用指针的表达式,例如
*fa
或 *fb
.
这是一个演示程序,显示指针 fa
和 fb
的值没有改变。
#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;
}
程序输出可能看起来像
fa = 0x7ffff85444f0, fb = 0x7ffff85444f4
fa = 0x7ffff85444f0, fb = 0x7ffff85444f4
正如所见,指针在函数的开头和结尾具有相同的值。交换的是指向对象的值。
并且指针fa
和fb
不影响main中声明的指针pa
和pb
。因为指针 fa
和 fb
作为函数的局部变量获取存储在指针 pa
和 pb
.
- 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
如果你的意思是在输入 swap
之后,那么是的。那是对的。参数作为副本传递,这意味着在该函数内部 fa
和 fb
从调用者那里获得 pa
和 pb
的副本。
- 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
根本没动过。它们被取消引用。这意味着,它们指向的地址受到影响。您可以使用 printf
打印那些指针变量的内容。他们不会改变。
相反,a
和 b
的内容已更改。
顺便说一句:您的 printf
陈述没有多大意义。您应该在函数调用之前和之后打印以查看效果。
当您将指针传递给您的函数时,您传递的是一个包含地址的变量。当您取消引用 fa(或 fb)时,您将获得该地址的实际值。所以当你修改它时,你修改了两个指针的值,因为它们指向同一个地址。
要更好地理解指针,您可以使用实际的假地址。假设变量 '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);
}
不要忘记 int* 是一个指向 int 的指针类型的变量。它的意思是该变量包含一个int类型变量的地址。实际上它只是指向内存。你可以这样写
int* a = 0x9000;
你会有一个指向地址 0x9000 的 int 类型的指针。那将是有效的语法,但您的 OS 会抱怨您无权访问该地址。如果你写
long* a = 0x9000;
唯一的区别是取消引用时获得的字节数。当你取消引用一个指针时,你会得到该类型包含的字节数。对于 int* 类型,当您取消引用时,您将获得从地址 0x9000 开始的 4 个字节(32 位)。使用 long* 类型,您将获得从地址 0x9000 开始的 8 个字节(64 位)。
int* 或 long* 类型变量的大小是相同的,因为这仅取决于您的架构 CPU。因此,对于这两者,您将获得一个具有相同大小的指针类型变量。唯一的区别是取消引用时获得的字节数。
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
分别。 fa
和 fb
(以及 pa
和 pb
)的值永远不会改变。
我修改了你的代码如下:
#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;
}
当运行时,它给出输出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
所以,我们可以看到以下都是正确的:
fa == pa == &a
*fa == *pa == a == 5 // before swap, 7 after swap
fb == pb == &b
*fb == *pb == b == 7 // before swap, 5 after swap
- 地址值可能会从 运行 变为 运行 - 重要的是
fa
和pa
以及&a
都是 相同 值。