以下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
保留在函数中分配给它的地址?
答案 0 :(得分:5)
由于这是C,所以不能通过引用传递指针而不传入指针指针(例如,void **
而不是void *
指向指针)。您需要返回新指针。发生了什么:
f(a1);
将指针(NULL
)的值作为a
的堆栈参数值。 a
获取此值,然后重新分配一个新值(malloc
ed地址)。当它按值传递时,a1
没有任何变化。
如果这是C ++,你可以通过引用传递指针来实现你想要的东西:
void f(void *&a);
答案 1 :(得分:4)
将指针a1
传递给您的函数,无法更改a1
指向的位置。指针是按值传递,因此在f1
中,您只需更改a
所持地址的副本。如果要更改指针,即为传入的指针分配新内存,则需要将指针传递给指针:
void f1(void **a)
{
// ...
*a = malloc(sizeof(int));
// ...
答案 2 :(得分:3)
要通过函数调用更改变量,该函数需要具有与参数相关的引用语义。 C没有本机引用变量,但可以通过获取地址和传递指针来实现引用语义。
一般而言:
void mutate_thing(Thing * x) // callee accepts pointer
{
*x = stuff; // callee derefences ("*")
}
int main()
{
Thing y;
mutate_thing(&y); // caller takes address-of ("&")
}
在您的情况下,Thing
为void *
:
void f(void ** pv)
{
*pv = malloc(12); // or whatever
}
int main()
{
void * a1;
f(&a1);
}
答案 3 :(得分: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;
}