通过调用另一个函数将指针转移到某个地址

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;
}