Wil*_*ill 7 c pointers arguments void-pointers argument-passing
以下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);
}
[...]
Run Code Online (Sandbox Code Playgroud)
结果是
a1 address = (nil)
f(a) address = (nil)
a address = 0xb3f010
data = 3
a1 address = (nil)
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)
为什么不在a1函数中保留已分配给它的地址?
因为这是C,所以不能通过引用传递指针而不传入指针指针(例如,void **而不是void *指向指针).您需要返回新指针.怎么了:
f(a1);
Run Code Online (Sandbox Code Playgroud)
将指针(NULL)的值作为堆栈参数值推送a.a获取此值,然后重新分配一个新值(malloced地址).因为它是通过值传递的,所以没有任何变化a1.
如果这是C++,你可以通过引用传递指针来实现你想要的:
void f(void *&a);
Run Code Online (Sandbox Code Playgroud)
传递指向a1函数的指针时,您无法更改a1指向的位置。该指针是通过值传递的,因此在f1您只需更改持有的地址的副本a。如果要更改指针,即为传入的指针分配新的内存,则需要将指针传递给指针:
void f1(void **a)
{
// ...
*a = malloc(sizeof(int));
// ...
Run Code Online (Sandbox Code Playgroud)
要通过函数调用更改变量,函数需要具有与参数相关的引用语义。C 没有本机引用变量,但可以通过获取地址和传递指针来实现引用语义。
一般来说:
void mutate_thing(Thing * x) // callee accepts pointer
{
*x = stuff; // callee derefences ("*")
}
int main()
{
Thing y;
mutate_thing(&y); // caller takes address-of ("&")
}
Run Code Online (Sandbox Code Playgroud)
在你的情况下,Thing是void *:
void f(void ** pv)
{
*pv = malloc(12); // or whatever
}
int main()
{
void * a1;
f(&a1);
}
Run Code Online (Sandbox Code Playgroud)