1

C言語でパラメータを参照渡しする方法を理解しようとしています。そこで、パラメーターの受け渡しの動作をテストするために、次のコードを書きました。

#include <stdio.h>
#include <stdlib.h>

void alocar(int* n){
   n = (int*) malloc( sizeof(int));
   if( n == NULL )
      exit(-1);
   *n = 12;
   printf("%d.\n", *n);
}
int main()
{
   int* n;
   alocar( n );
   printf("%d.\n", *n);
   return 0;
}

ここに印刷されています:

12.
0.

例 2:

#include <stdio.h>
#include <stdlib.h>

void alocar(int* n){
   *n = 12;
   printf("%d.\n", *n);
}

int main()
{
   int* n;
   n = (int*) malloc(sizeof(int));
   if( n == NULL )
      exit(-1);
   alocar( n );
   printf("%d.\n", *n);
   return 0;
}

それは印刷しました:

12.
12.

この 2 つのプログラムの違いは何ですか?

4

5 に答える 5

6

C は値渡しであり、参照渡しを提供しません。あなたの場合、ポインター(ポインターが指すものではない)が関数パラメーターにコピーされます(ポインターは値で渡されます-ポインターの値はアドレスです)

void alocar(int* n){
   //n is just a local variable here.
   n = (int*) malloc( sizeof(int));
  //assigning to n just assigns to the local
  //n variable, the caller is not affected.

次のようなものが必要です。

int *alocar(void){
   int *n = malloc( sizeof(int));
   if( n == NULL )
      exit(-1);
   *n = 12;
   printf("%d.\n", *n);
   return n;
}
int main()
{
   int* n;
   n = alocar();
   printf("%d.\n", *n);
   return 0;
}

または:

void alocar(int** n){
   *n =  malloc( sizeof(int));
   if( *n == NULL )
      exit(-1);
   **n = 12;
   printf("%d.\n", **n);
}
int main()
{
   int* n;
   alocar( &n );
   printf("%d.\n", *n);
   return 0;
}
于 2010-11-11T20:36:51.583 に答える
3

実際には、最初のものが壊れていることを除いて、それほど大きな違いはありません. :) (どちらもそうですが、最初の方が壊れています)。

2番目のケースで何が起こるかを説明しましょう:

  • nタイプの変数がpointer-to-intスタックに割り当てられます
  • タイプの新しい変数がintスタックに割り当てられ、そのアドレスが変数に格納されますn
  • 関数alocarが呼び出され、 variable のコピーが渡されますn。これは、型の変数のアドレスのコピーですint
  • この関数は、intが指す変数nを 12に設定します。
  • nこの関数は、 (12)が指す変数の値を出力します。
  • 関数が返す

最初のケース:

  • nタイプの変数がpointer-to-intスタックに割り当てられます
  • 関数alocarは変数のコピーで呼び出されますn(まだ初期化されていない - 不明な値が含まれています)
  • タイプの新しい変数がメモリ内に作成され、関数内intの変数のローカル コピーがその新しい変数を指すように設定されます。nalocar
  • 変数 ( の関数のローカル コピーが指すn) は 12 に設定され、出力されます。
  • この関数は、再び main() 関数で戻ります。
  • mainの元のn変数はまだ初期化されていないため、メモリ内のランダムな場所を指します。したがって、メモリ内のランダムな場所の値が出力されます (プログラムがクラッシュする可能性があります)。

また、malloc() によって割り当てられたメモリを解放しないため、両方のプログラムが壊れています。

于 2010-11-11T20:40:48.937 に答える
1

を指すものではなく、 ninの値を変更したいので、ポインタを渡す必要があります。inの型はであるため、 へのパラメーターは型である必要があります。mainn nmainint *alocarint **

void alocar(int **n)
{
  *n = malloc(sizeof **n); // note no cast, operand of sizeof
  if (!*n)
    exit(-1);

  **n = 12;
  printf("%d\n", **n);
}

int main(void)
{
  int *n;
  alocar(&n);
  printf("%d\n", *n);  // we've already tested against n being NULL in alocar
  free(n);             // always clean up after yourself
  return 0;
}
于 2010-11-11T21:15:24.413 に答える
0

最初のプログラムで何が起こったか見てください。

alocar を呼び出す前に、main に変数 n があり、未定義の場所を指しています。

 main()::n [  X--]--->(?)

(角括弧内に未定義の値があり、X としてマークされています)。次に、alocar を呼び出します。alocar のスコープには、元の var のコピーを持つ別の変数があります。

 main()::n   [  X--]--->(?)
 alocar()::n [  X--]-----^

次に、いくつかのメモリを割り当てます。

 main()::n   [  X--]--->(?)
 alocar()::n [  *--]--->[   Y  ]

割り当てられた var に値を割り当てます。

 main()::n   [  X--]--->(?)
 alocar()::n [  *--]--->[  12  ]

戻る。alocar()::n は alocar() が実行されている間のみ有効であるため、削除されました。

 main()::n   [  X--]--->(?)
                        [  12  ]

main()::n はまだ未定義の場所を指しています... (値 0 を格納する可能性があります) そして、誰も割り当てられた場所を指していません。

于 2010-11-11T21:48:49.220 に答える
0

nosが投稿した答えは正しいです。

nまた、投稿された 2 つのプログラムのうち最初のプログラムは、多くのシステムで実際にクラッシュすることに注意してください。main() の printf 行が、設定されていないmain の pointer を逆参照しようとすると、次のようになります。

   printf("%d.\n", *n);
于 2010-11-11T20:42:40.960 に答える