通过调用另一个函数将指针转移到某个地址
Shifting pointer to some address by calling another function
为什么在这段代码中指针移动到另一个位置:
#include <stdio.h>
void f(int *p)
{
int j=2;
p=&j;
printf("%d\n%p\n%d\n",*p,&j,p);
}
int main(void)
{
int *q;
int m=98;
q=&m;
f(q);
printf("%p ",q);
return 0;
}
输出:
2
0x7ffff5bf1bcc
0x7ffff5bf1bcc
0x7ffff5bf1bc8
我知道当函数 f() 完成时打印值 j
和 地址 j
内存 被 j
占用返回堆栈,但 IMO p
应该继续指向该位置,即使在函数结束后它应该打印 same main 中的地址。这有什么问题吗?
考虑到您在实际代码中的意思是 printf("%p ", (void *)q);
,
不,C 中的函数参数是按值传递的。它不会将对参数所做的更改反映到实际使用的参数(在函数调用中)本身。
换句话说,函数参数在函数(调用)范围内是局部的,对它们所做的任何更改都不会反映到实际参数中。
所以,如果你需要改变一个指针,你需要传递一个指向需要改变的指针的指针。
考虑一个相当轻松但现实的场景。
void f (int x) { x = 10; }
int main(void) { f(5); printf ("%d", 5); return 0;}
现在,您希望它打印 10
吗?
也就是说,一个建议。始终将 %p
转换说明符的参数转换为 (void *)
(如果尚未转换)。 printf()
是一个可变参数函数,对于指针,不会发生默认参数提升,因此提供的参数类型需要显式匹配预期类型。否则,技术上是 undefined behavior.
了解指针和指向指针的指针之间的区别 - 传递的指针 p 无疑很好地改变了它所指向的变量的值 ( m), 但要更改它指向的内存位置 - 你需要一个指向指针的指针。
在@SouravGhosh 所说的基础上进行扩展,当您传入指向 int 的指针时,您正在制作指针的副本。如果您想更改指针,则需要双重间接并将指针传递给指向 int 的指针。第一个指针被复制,你可以直接影响第二个指针。
void f(int ** p)
{
int j = 2;
*p = &j;
printf("%d\n%p\n%p\n",*p,&j,p);
}
int main(void)
{
int ** q = (int **)malloc( izeof(int *));
int m = 98;
*q = &m;
f(q);
printf("%p ",q);
free(q);
return 0;
}
输出为
2
0xffffcbcc
0xffffcbcc
0xffffcbcc
如果你这样做,你会发现它永远不会改变:
#include <iostream>
#include "Header2.h"
#include "header1.h"
#include <stdio.h>
void f(int *p)
{
int j = 2;
p = &j;
printf("%d\n%p\n%p\n", *p, &j, p);
}
int main(void)
{
int *q;
int m = 98;
q = &m;
printf("Value of pointer q before calling f() =%p ", q);
f(q);
printf("Value of pointer q after calling f() =%p ", q);
return 0;
}
为什么在这段代码中指针移动到另一个位置:
#include <stdio.h>
void f(int *p)
{
int j=2;
p=&j;
printf("%d\n%p\n%d\n",*p,&j,p);
}
int main(void)
{
int *q;
int m=98;
q=&m;
f(q);
printf("%p ",q);
return 0;
}
输出:
2
0x7ffff5bf1bcc
0x7ffff5bf1bcc
0x7ffff5bf1bc8
我知道当函数 f() 完成时打印值 j
和 地址 j
内存 被 j
占用返回堆栈,但 IMO p
应该继续指向该位置,即使在函数结束后它应该打印 same main 中的地址。这有什么问题吗?
考虑到您在实际代码中的意思是 printf("%p ", (void *)q);
,
不,C 中的函数参数是按值传递的。它不会将对参数所做的更改反映到实际使用的参数(在函数调用中)本身。
换句话说,函数参数在函数(调用)范围内是局部的,对它们所做的任何更改都不会反映到实际参数中。
所以,如果你需要改变一个指针,你需要传递一个指向需要改变的指针的指针。
考虑一个相当轻松但现实的场景。
void f (int x) { x = 10; }
int main(void) { f(5); printf ("%d", 5); return 0;}
现在,您希望它打印 10
吗?
也就是说,一个建议。始终将 %p
转换说明符的参数转换为 (void *)
(如果尚未转换)。 printf()
是一个可变参数函数,对于指针,不会发生默认参数提升,因此提供的参数类型需要显式匹配预期类型。否则,技术上是 undefined behavior.
了解指针和指向指针的指针之间的区别 - 传递的指针 p 无疑很好地改变了它所指向的变量的值 ( m), 但要更改它指向的内存位置 - 你需要一个指向指针的指针。
在@SouravGhosh 所说的基础上进行扩展,当您传入指向 int 的指针时,您正在制作指针的副本。如果您想更改指针,则需要双重间接并将指针传递给指向 int 的指针。第一个指针被复制,你可以直接影响第二个指针。
void f(int ** p)
{
int j = 2;
*p = &j;
printf("%d\n%p\n%p\n",*p,&j,p);
}
int main(void)
{
int ** q = (int **)malloc( izeof(int *));
int m = 98;
*q = &m;
f(q);
printf("%p ",q);
free(q);
return 0;
}
输出为
2 0xffffcbcc 0xffffcbcc 0xffffcbcc
如果你这样做,你会发现它永远不会改变:
#include <iostream>
#include "Header2.h"
#include "header1.h"
#include <stdio.h>
void f(int *p)
{
int j = 2;
p = &j;
printf("%d\n%p\n%p\n", *p, &j, p);
}
int main(void)
{
int *q;
int m = 98;
q = &m;
printf("Value of pointer q before calling f() =%p ", q);
f(q);
printf("Value of pointer q after calling f() =%p ", q);
return 0;
}