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 に答える