2011-07-27 6 views
0

Whew!長いタイトル...ここに説明する疑似コードがあります。C - 関数へのポインタの引き渡しとその関数内で同じポインタを別の関数に渡す

int main(){ 
int* ptr = function1(); //the data that ptr points to is correct here 
function2(ptr); 
} 

int function2(int* ptr){ 
//the data that ptr points to is still correct 
int i; 
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); //since ptr points to a contiguous block of memory 
function3(ptr); 
} 

int function3(int* ptr){ 
//the data that ptr points to is INCORRECT!!! 
} 

function3のデータが間違っているのはなぜですか?

注:function1はmalloc()を実行し、そのメモリへのポインタを返します。

実際のコード

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

//Structures 
struct hash_table_data_ 
{ 
    int key, data; 
    struct hash_table_data_ *next, *prev; 
}; 

struct hash_table_ 
{ 
    int num_entries; 
    struct hash_table_data_ **entries; 
}; 

typedef struct hash_table_data_ hash_table_data; 
typedef struct hash_table_ hash_table; 

//Prototypes 
hash_table *new_hash_table(int num_entries); 
int hash_table_add(hash_table *ht, int key, int data); 
int hash_table_loader(hash_table* ht); 

//Main 
int main() 
{ 
    int num_entries = 8;//THIS MUST BE AUTOMATED 

    hash_table* ht = new_hash_table(num_entries); 
    hash_table_loader(ht); 

    return 0; 
} 

//Function Definitions 
hash_table *new_hash_table(int num_entries) 
{ 
    hash_table* ht = (hash_table*) malloc(sizeof(hash_table)); 

    hash_table_data* array = malloc(num_entries * sizeof(hash_table_data)); 
    int i; 
    for (i=0;i<num_entries;i++) 
    { 
     array[i].key = -1; 
     array[i].data = -1; 
     array[i].next = NULL; 
     array[i].prev = NULL; 
    } 

    ht->entries = &array; 
    ht->num_entries = num_entries; 

    return ht; 
} 

int hash_table_add(hash_table *ht, int key, int data) 
{ 
    //VERIFY THAT THE VALUE ISN'T ALREADY IN THE TABLE!!!!!!!!!!! 
    int num_entries = ht->num_entries; 
    hash_table_data* array = *(ht->entries); //array elements are the LL base 
    int hash_val = key%num_entries; 

    printf("adding an element now...\n"); 
    printf("current key: %d\n", array[hash_val].key); 

    int i; 
    for(i=0;i<num_entries;printf("%d\n", (*(ht->entries))[i].key),i++);//DATA IS INCORRECT!!!! 

    if (array[hash_val].key == -1)//is this the base link? 
    { 
     printf("added a new base link!\n"); 
     array[hash_val].key = key; 
     array[hash_val].data = data; 
     array[hash_val].next = NULL; 
     array[hash_val].prev = &(array[hash_val]); 
    } 
    else//since it's not the base link...do stuff 
    { 
     hash_table_data* new_link = malloc(sizeof(hash_table_data)); 
     new_link->key = key;//set the key value 
     new_link->data = data;//set the data value 
     if (array[hash_val].next == NULL)//we must have the second link 
    { 
     printf("added a new second link!\n"); 
     new_link->prev = &(array[hash_val]); //set the new link's previous to be the base link 
     array[hash_val].next = new_link; //set the first link's next 
    } 
     else//we have the 3rd or greater link 
    { 
     printf("added a new 3rd or greater link!\n"); 
     hash_table_data next_link_val = *(array[hash_val].next); 
     while (next_link_val.next != NULL)//follow the links until we reach the last link 
     { 
      next_link_val = *(next_link_val.next);//follow the current link to the next 
     } 
     //now that we've reached the last link, link it to the new_link 
     next_link_val.next = new_link; //link the last link to the new link 
     new_link->prev = &(next_link_val); //link the new link to the last link 
    } 
    } 

    return 0; 
} 

int hash_table_loader(hash_table* ht) 
{ 
    int i; 
    for(i=0;i<(ht->num_entries);printf("%d\n", (*(ht->entries))[i].key),i++); //DATA IS STILL CORRECT HERE 

    FILE *infile; 
    infile = fopen("input.txt", "r"); 
    while(!feof(infile)) 
    { 
     int key,data; 
     fscanf(infile, "%d %d", &key, &data); 
     hash_table_add(ht, key, data); 
    } 
    fclose(infile); 
} 

を注:この問題は、最初の時間hash_table_addを生じる()が呼び出されます。

+1

この最適化コードはありますか? 'ptr'が間違っていることをどのように知っていますか? – MSN

+0

データは正しいはずです。 http://sscce.org/ –

+1

'function1()'の定義を表示します。 – Mahesh

答えて

7

あなたの最初の問題はここにある:

ht->entries = &array;

あなたが関数にローカルな変数hash_table_data* arrayを指すhash_table_data**を保持するための構造を引き起こします。関数を終了して構造体へのポインタを返します。構造はまだ(それがmalloc()経由で割り当てられた存在、そしてarrayポイントがまだ存在するが、array自体が。したがって、構造内のこのポインタが現在無効ではありません。

私の知る限り、そこにその原料ここでポインタをポインタに保持する理由はありません。エントリタイプとしてhash_table_data*を使用し、arrayをその構造体メンバにコピーしてください。ポインタも値です。

+0

エントリはポインタへのポインタですので、ht-> entries = &array;として割り当てるのが理にかなっています。連続したメモリチャンク。 –

+0

+1:おそらく私は遅すぎます。 – Mahesh

+0

@nick_name:機能の範囲内であれば意味があります。 'array'はスタックにありますが、' array'が指す値はヒープ上にあります。関数が戻ると、スタックにある変数は破壊されます。 – Mahesh

0

私は、これはナンセンスであるあなたが

for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); 

間違って繰り返すと思います。

あなたはこのようにそれを書き換える必要があります。

for(i=0;i<length;i++) 
    printf("%d\n", ptr[i]); 

(*ptr)[i]

はちょうど間違っている、あなたが考えてみれば、それは意味がありません。

*ptrは、intのポイント型配列の最初の要素です。 ptr[i]はthieriです。これが必要です。

慎重にSection 6をお読みください。

この質問に基づくアドバイスのカップル:けれども(それだけでほとんど必要ありません、使用コンマ演算子でこのfor文のようなovercomplicatedコードを記述しないでください

  1. と混乱するのではなく、ミスをするだけでなくつながりますこの特定の例では間違いなし)
  2. 間違いを注意深く見て、機能上のすべてを責めないでください。あなたのコードがうまくいかない場合は、間違った場所を見つけてそれを証明してみてください。この例では、あなたのコードをテストした人が正しいと思います。関数は間違いなくエラーの原因ではありません。
+0

さて、実際のコードを見て、私の答えは時代遅れです。 – unkulunkulu

+0

彼の場合、 'ptr'は実際にはintへのポインタへのポインタです。 –

+0

@Karl、私のコメントを参照してください、私は彼が実際のコードを投稿する前に答えを投稿しました – unkulunkulu

0
hash_table *new_hash_table(int num_entries) 
{ 
    hash_table* ht = (hash_table*) malloc(sizeof(hash_table)); 

    hash_table_data* array = malloc(num_entries * sizeof(hash_table_data)); 

    // .... 

    ht->entries = &array; // Problem 

    // ... 
    return ht; 
} // Life time of array ends at this point. 

ローカル変数arrayの参照を取り、関数復帰したあとは、もはや有効であるht->entriesに代入されていません。

+0

ニース!ありがとう!私はその変更をテストしています。 –

関連する問題