8

以下 C 代码段:

[...] 
void f1(void* a){
  printf("f(a) address = %p \n",a);
  a = (void*)(int*)malloc(sizeof(int));

  printf("a address = %p \n",a);
  *(int*)a = 3;

  printf("data = %d\n",*(int*)a);
}

void f(void){
  void* a1=NULL;
  printf("a1 address = %p \n",a1);

  f1(a1);

  printf("a1 address = %p \n",a1);
  printf("Data.a1 = %d\n",*(int*)a1);
}
[...]

结果是

a1 address = (nil) 
f(a) address = (nil) 
a address = 0xb3f010 
data = 3
a1 address = (nil) 
Segmentation fault (core dumped)

为什么不在a1函数中保留已分配给它的地址?

4

4 回答 4

9

由于这是 C,如果不传递指向指针的指针(例如,void **而不是void *指向指针),就不能通过引用传递指针。您需要返回新指针。怎么了:

f(a1);

将指针 ( NULL) 的值作为 的堆栈参数值推送aa拾取这个值,然后给自己重新分配一个新值(malloced 地址)。因为它是按值传递的,所以a1.

如果这是 C++,你可以通过引用传递指针来实现你想要的:

void f(void *&a);
于 2012-09-16T17:22:00.033 回答
9

将指针传递a1给您的函数,您无法更改a1指向的位置。指针是按值传递的,因此f1您只需更改 . 持有的地址的副本a。如果要更改指针,即为传入的指针分配新内存,则需要将指针传递给指针

void f1(void **a)
{
    // ...
    *a = malloc(sizeof(int));
    // ...
于 2012-09-16T17:22:02.350 回答
4

要通过函数调用更改变量,函数需要具有关于参数的引用语义。C 没有原生引用变量,但可以通过取地址和传递指针的方式实现引用语义。

一般来说:

void mutate_thing(Thing * x)    // callee accepts pointer
{
    *x = stuff;                 // callee derefences ("*")
}

int main()
{
    Thing y;
    mutate_thing(&y);           // caller takes address-of ("&")
}

在你的情况下,Thingvoid *

void f(void ** pv)
{
    *pv = malloc(12);   // or whatever
}

int main()
{
     void * a1;
     f(&a1);
}
于 2012-09-16T17:25:06.183 回答
1

基于 Kerrek SB 的示例,我用这个来演示 void 指针到指针作为参数以及如何使用它。

#include <stdio.h>

void test(void ** jeez)
{
  *jeez = (void *) (int) 3;
}


int main (int argc, char* argv[])
{
void *a;
test(&a);

int b = *(int *)&a;
printf("value returned = %d\n", b);

return 0;
}
于 2014-09-01T03:53:26.893 回答