0

Cでハッシュテーブルを「構築」したい(読み:mallocとmemset)。これを行うために、次のような関数を作成しました。

int maketable(struct hash_entry **table, int size){

    table = (struct hash_entry **)malloc(size*sizeof(struct hash_entry *));
    int i = 0;
    for (; i<size; i++) {
        memset(table[i], '\0', sizeof(struct hash_entry *));
    }
    return 0;

}

テーブルが次のように宣言されていることを考えると

struct hash_entry **table[size]

このコードを入力する前に、maketable から戻ったときに何も失うことはありませんよね?

編集:指しているデータを変更する限り、変更が保持されることを保証しtableますか?maketable()table

編集 II: hash_entries へのポインターへのポインターの配列を割り当てようとしています

4

3 に答える 3

4

コードはローカルtable変数に代入していますが、呼び出し元は影響を受けません。これにより、メモリ リークが発生します。

関数の外側では、構造体 hash_entry のポインターへのポインターの配列として table を宣言しました。構造体ハッシュ エントリへのポインターの配列が必要なだけだと思います。

実際にtable配列として宣言する場合、そのスペースを malloc する必要はありません。その中のすべての要素を NULL に設定するためのループが必要なだけです (各要素をゼロに memset しないでください)。

目標がテーブル全体を割り当てることである場合、これはあなたが探しているものです:

struct hash_entry **table;
...
int maketable(struct hash_entry ***table, int size){

    *table = malloc(size* sizeof **table);
    int i = 0;
    for (; i<size; i++) {
       (*table)[i] = NULL;
    }
    return 0;
}

のように呼ぶ

maketable(&table,100);

次のようにテーブルを返すようにしたいと思います。

struct hash_entry ** maketable(int size){
   return calloc(size, sizeof(struct hash_entry *));
}

宣言struct hash_entry **table[size]が本当にあなたが望むものである場合は、maketable() 関数が実際に何をすべきかを私たちに伝える必要があります (例えば、そのテーブルの要素の 1 つとして動的に割り当てられた「配列」が必要ですか?

于 2010-01-26T23:13:14.287 に答える
2

malloctoの結果を代入する必要があり* tableます。そうしないと、関数の外では見えません。

また、これを使用する典型的な方法は、ハッシュテーブルへのポインターを宣言し、そのポインターのアドレスを関数に渡すことです。

于 2010-01-26T23:05:40.567 に答える
1

いいえ、タイプが一致しません。

ハッシュ エントリのテーブル (つまりtable[i]isの型)、 hash_entries へのポインタstruct hash_entryのテーブル(つまりisの型)、または何か他のものを割り当てようとしていますか? コードの読み方に基づいて、最初のケースを想定していますが、それが間違っている場合はお知らせください。 table[i]struct hash_entry *

のテーブルを動的に割り当てると仮定するとstruct hash_entry、呼び出し元でのテーブルの宣言は次のようになります。

struct hash_entry *table; // 1 *, no array dimension

関数は次のように呼び出す必要があります

int result = maketable(&table, number_of_elements);

そして次のように定義されます

int maketable (struct hash_entry **table, size_t size)
{
  int r = 0;

  // sizeof **table == sizeof (struct hash_entry)
  *table = malloc(sizeof **table * size);
  // *ALWAYS* check the result of malloc()
  if (*table)
  {
    size_t i;
    for (i = 0; i < size; i++)
      memset(&(*table)[i], 0, sizeof (*table)[i]);
    r = 1;
  }
  return r;
}

指摘すべきことがいくつかあります。まず、 の結果をキャストしないでくださいmalloc()。C89 の時点では、その必要はありません。 stdlib.h を含めるのを忘れた場合、またはmalloc()スコープ内にプロトタイプがない場合、キャストは診断を抑制します。sizeof次に、型の代わりにオブジェクトに対して演算子を使用できます。これにより、いくつかのメンテナンスの頭痛の種を減らすことができます (つまり、パラメーター リストで の型を変更した場合、それに伴って呼び出し tableを変更する必要はありません)。sizeof

最後に、テーブルのアドレスが関数に渡されていることに注意してください。ポインター値に書き込もうとしているので、そのポインターにポインターを渡す必要があります。

へのポインターのテーブルを作成しようとしていた場合struct hash_entry、コードはほとんど同じで、間接的なレベルが追加されているだけです。

呼び出し元でのテーブルの宣言は、

struct hash_entry **table; // 2 *, no array dimension

関数は次のように呼び出す必要があります

int result = maketable(&table, number_of_elements);

そして次のように定義されます

int maketable (struct hash_entry ***table, size_t size)
{
  int r = 0;

  // sizeof **table == sizeof (struct hash_entry *)
  *table = malloc(sizeof **table * size);
  // *ALWAYS* check the result of malloc()
  if (*table)
  {
    size_t i;
    for (i = 0; i < size; i++)
      (*table)[i] = NULL;
    r = 1;
  }
  return r;
}

EDITmaketable例にバグがありました。table添え字を適用する前に逆参照する必要があります(*table)[i]。テーブル ポインタ自体ではなく、 table を指すものに添字を適用しています。

混乱して申し訳ありません。

于 2010-01-26T23:27:04.480 に答える