0

全て

動的な2D配列宣言の非常に単純なCコードを記述し、それをで初期化してmemsetから値を出力しています。私のコードは次のようなものです。

float **env;
int i,j,num;

printf("Enter a number : \n");
scanf("%d",&num);

env = (float **)malloc(num*sizeof(float *));

for(i=0;i<num;i++)
{env[i] = (float *)malloc(num*sizeof(float));}

memset(env, 0, sizeof(float)*num*num);

for(i=0;i<num;i++)
{  for (j=0;j<num;j++)
   {
      printf("%f\t",env[i][j]);
      if (j == num -1)
       { printf("\n\n");}
    }
}

for(i=0;i<num;i++)
{free(env[i]);
}

free(env);

プログラムをコンパイルするとき、コンパイルエラーや警告はありませんが、値を印刷しようとすると、それらを印刷できません。次に、プログラムをデバッグしました。memsetステートメントの後にenv 2D変数が次のよう CXX0030: Error: expression cannot be evaluatedに表示され、値を出力するとウィンドウが表示されます。

Unhandled exception at 0x008b1e27 in ***.exe: 0xC0000005: Access violation reading location 0x00000000.

2 forループを使用して2D配列envを0に明示的に初期化しようとしましたが、これは完全に機能し、値を出力することもできますが、を使用すると機能しませんmemset。誰かが私を助けてくれるととても助かります。ありがとうございました。

4

3 に答える 3

3

まず、通常のアドバイス: の下で型名を使用するのsizeofをやめ、 の結果をキャストするのをやめmallocます。これは、それがどのように見えるべきかです

env = malloc(num * sizeof *env);

for (i = 0; i < num; i++)
  env[i] = malloc(num * sizeof *env[i]);

一般に、次のパターンに従ってメモリ割り当てを作成することをお勧めします

some_ptr = malloc(N * sizeof *some_ptr);

次に、この手法を使用して作成する「配列」は、従来の C スタイルの連続した 2D 配列ではありません。代わりに、完全に無関係な 1D 配列の束から組み立てられた「シミュレートされた」2D 配列を取得します。後者は、メモリ内にランダムに散らばっている可能性があります。これは、配列を連続オブジェクトとして処理できないことをすぐに意味します。その間、あなたのmemset呼び出しはまさにそれをしようとします。このようにすることはできません。あなたの場合、サイクルを使用して、各 1D サブアレイを個別にゼロにする必要があります。

ただし、1D サブ配列を個別に割り当てる代わりに、それらすべてを単一のメモリ ブロックとして割り当てることができます。

assert(num > 0);
env = malloc(num * sizeof *env);
env[0] = malloc(num * num * sizeof *env[0]);

for (i = 1; i < num; ++i)
  env[i] = env[i - 1] + num;

上記のように割り当てられた場合、配列のデータは 1 つの連続したメモリ ブロックに格納されますが、その配列を操作するときに何をしているのかを理解する必要があります。たとえばmemset、配列データを ing すると、次のようになります。

memset(*env, 0, num * num * sizeof **env);

また

memset(&env[0][0], 0, num * num * sizeof env[0][0]);

(これは同じことです)。

于 2012-11-03T19:07:24.167 に答える
2

を削除して代わりにmemset使用すると、割り当てられたメモリがゼロで初期化されます。今行っているのは、割り当てたばかりのポインターをゼロにすることです。callocmalloc

于 2012-11-03T18:55:42.417 に答える
2

マイケルの答えに加えて、それが連続したメモリのチャンクを与えfloat **envないことを理解することが重要です。メモリの連続チャンクへのポインタを提供し、それらのメモリ位置のそれぞれにメモリの連続チャンクへのポインタがありますが、それらのチャンクが整列されているという保証はありません。

たとえば、次のようにします。

int *x = malloc(sizeof(int)); 
int *y = malloc(sizeof(int)); 

x と y がメモリ内で連続しているとは限りませんが、これはコードが想定していることです。

于 2012-11-03T19:01:06.753 に答える