2011-07-27 37 views
0

Whe!長題目...這裏有一些僞代碼來解釋這種措詞: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!!! 
} 

爲什麼函數3中的數據不正確?

注意: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**指向變量hash_table_data* array這是本地的功能;那麼你退出函數並返回一個指向結構體的指針。結構仍然存在(這是據我可以告訴通過malloc()分配,而且仍然存在array點東西,但array本身並沒有,因此,結構在這個指針現在是無效的。

,有沒有理由在這裏持有指針指針,只需使用hash_table_data*作爲條目類型,並將array複製到該結構成員中。指針也是值。

+0

條目是指向指針的指針,因此將它指定爲ht-> entries = &array;10另外,指向第一個塊的數組連續的內存塊。 –

+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是指向整數的整數的第一個元素。 ptr[i] is thi i第一,這是你所需要的。請仔細閱讀Section 6

一對夫婦的建議基於這樣一個問題:

  1. 不要寫過於複雜的代碼,這樣for語句逗號操作使用,它只是很少需要,並不僅導致混亂,但失誤(雖然在這個特殊的例子中沒有錯誤)
  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

不錯!謝謝!我正在測試這個變化。 –