2012-04-27 60 views
1

我應該遵循下列標準:下使用malloc和複製陣列

實現功能answer4(指針參數和n):

  1. 準備使用的n個項目malloc() student_record的陣列。

  2. 將學生記錄從參數複製到數組中n 次。

  3. 返回數組。

我附帶下面的代碼,但它顯然不正確。什麼是實施這個的正確方法?

student_record *answer4(student_record* p, unsigned int n) 
{ 
    int i; 
    student_record* q = malloc(sizeof(student_record)*n); 
    for(i = 0; i < n ; i++){ 
     q[i] = p[i]; 
    } 
    free(q); 
    return q; 
}; 
+1

如果功課,請標記爲家庭作業。它可能有助於分配一些東西給一個。 – bmargulies 2012-04-27 14:59:34

+1

請注意,如果您需要'n'個實例,則循環條件應該是'i ysap 2012-04-27 15:00:20

+2

您是否意識到,在您的解決方案中,數組將充滿指向同一實例的指針?你不是真的在那裏複製。 – Raveline 2012-04-27 15:00:41

回答

1
p = malloc(sizeof(student_record)*n); 

這是個問題:你覆蓋p輸入參數,所以你不能引用你行之後被移交數據。

這意味着你的內循環讀取初始化數據。

此:

return a; 

是有問題的太 - 它會返回一個指針到一個局部變量,這是不好的 - 那指針變爲無效,一旦函數返回。

你需要的是這樣的:

student_record* ret = malloc(...); 

for (int i=...) { 
// copy p[i] to ret[i] 
} 

return ret; 
+0

student_record * answer4(student_record * P,無符號整型N) { \t INT I; \t student_record * q = malloc(sizeof(student_record)* n); \t爲(I = 0; I 2012-04-27 15:12:42

+0

不要釋放'q'!如果你這樣做,你返回一個無效的指針給調用者,這是無用的。當他/她完成該操作時,調用者將負責釋放該內存。 – Mat 2012-04-27 15:14:20

+0

student_record * answer4(student_record * p,unsigned int n) { \t int i; \t student_record * q = malloc(sizeof(student_record)* n); \t爲(I = 0; I 2012-04-27 15:18:37

1

1)您重新分配P,你想複製,通過調用malloc()陣列。

2)您不能返回本地堆棧的地址變量(a)。將a更改爲一個指針,malloc將其大小設爲p,然後將p複製到。 Malloc的內存是內存,所以你可以返回這樣的地址。

1

a[]是本地自動陣列。一旦從函數返回,它將從內存中刪除,所以調用函數不能使用返回的數組。

你可能想要做的是malloc一個新的數組(即,不是p),你應該爲其分配重複值並返回它的值而不釋放malloced內存。

1

嘗試使用更好的名稱,它可能有助於避免您在代碼中出現明顯的混淆錯誤。

student_record * answer4(const student_record *template, size_t n) 
{ 
... 
} 

這也使得代碼更清晰:

例如,具有啓動功能。請注意,我添加了const以更清楚地表明第一個參數是僅用於輸入的,並將第二個參數的類型設置爲size_t,這在處理「計數」和事物大小時很好。

0
student_record* answer4(student_record* p, unsigned int n) 
{ 
    uint8_t *data, *pos; 
    size_t size = sizeof(student_record); 
    data = malloc(size*n); 

    pos = data; 
    for(unsigned int i = 0; i < n ; i++, pos=&pos[size]) 
     memcpy(pos,p,size); 

    return (student_record *)data; 
}; 

你可以這樣做。

0

這編譯和,我想,你想要做什麼:

student_record *answer4(const student_record *const p, const unsigned int n) 
{ 
    unsigned int i; 
    student_record *const a = malloc(sizeof(student_record)*n); 
    for(i = 0; i < n; ++i) 
    { 
     a[i] = p[i]; 
    } 
    return a; 
}; 

幾點:

  1. 現有的陣列被確定爲p。你想從它複製。你可能不想釋放它(釋放它可能是調用者的工作)。
  2. 新陣列是a。你想複製到它。該函數不能釋放它,因爲調用者將需要它。因此,呼叫者必須負責釋放它,一旦呼叫者完成了它。
  3. 該數組有n個元素,索引爲0到n-1。表達指數上限的通常方法是i < n
  4. 我已經添加的const不是必需的,但寫得很好的代碼可能會包含它們。
1

在這個問題的代碼是不斷髮展得很快,但在這個答案的時候它包含以下兩行:

free(q); 
return q; 

這保證是錯誤的 - 調用free它的參數後點內存無效,隨後在使用q的值時可能發生任何事情。即你正在返回一個無效的指針。既然你回來q,不要釋放它!它變成了一個「呼叫者擁有的」變量,它成爲呼叫者的責任,釋放它。

0

Altought,以前有這個問題的好答案,我無法避免添加我自己的。由於我在Collegue了PASCAL編程,我習慣了這樣做,在C相關的編程語言:

void* AnyFunction(int AnyParameter) 
{ 
    void* Result = NULL; 

    DoSomethingWith(Result); 

    return Result; 
} 

這幫助我輕鬆調試,避免像一個提到的@ysap錯誤,相關指針。

重要的是要記住的問題是,該問題提到返回一個單一的指針,這是一個常見的警告,因爲一個指針,可以用來解決單個項目,或連續的數組!

這個問題建議使用一個數組作爲CONCEPT,帶指針,不使用陣列語法。

// returns a single pointer to an array: 
student_record* answer4(student_record* student, unsigned int n) 
{ 
    // empty result variable for this function: 
    student_record* Result = NULL; 

    // the result will allocate a conceptual array, even if it is a single pointer: 
    student_record* Result = malloc(sizeof(student_record)*n); 

    // a copy of the destination result, will move for each item 
    student_record* dest = Result; 

    int i; 
    for(i = 0; i < n ; i++){ 
    // copy contents, not address: 
    *dest = *student; 

    // move to next item of "Result" 
    dest++; 
    } 

    // the data referenced by "Result", was changed using "dest" 
    return Result; 
} // student_record* answer4(...) 

檢查,這裏沒有下標運算符,因爲用指針尋址。

請不要啓動一個pascal v.s. C火焰戰爭,這只是一個建議。