2009-06-15 98 views
1

我很想知道如何通過函數分配數據,並且在函數返回後仍然分配數據。這既適用於基本類型(int,char **)也適用於用戶定義的類型。以下是兩段代碼。雖然在分配結束後返回,但兩者都在函數內分配。通過函數分配數據(ANSI C)

int* nCheck = NULL; 
int nCount = 4; 

CallIntAllocation(nCheck, nCount); 

nCheck[1] = 3; // Not allocated! 
... 

CallIntAllocation(int* nCheck, int nCount) 
{ 

    nCheck = (int*)malloc(nCount* sizeof(int)); 
    for (int j = 0; j < nCount; j++) 
     nCheck[j] = 0; 
} 

換作以前同樣的行爲,雖然爲用戶定義類型:

typedef struct criteriatype 
{ 
    char szCriterio[256]; 
    char szCriterioSpecific[256]; 
} _CriteriaType; 

typedef struct criteria 
{ 
    int nCount; 
    char szType[128]; 
    _CriteriaType* CriteriaType; 
} _Criteria; 

... 
_Criteria* Criteria; 
AllocateCriteria(nTypes, nCriteria, Criteria); 
... 

void AllocateCriteria(int nTypes, int nCriteria[], _Criteria* Criteria) 
{ 
    int i = 0; 
    int j = 0; 

    Criteria = (_Criteria*)malloc(nTypes * sizeof(_Criteria)); 

    for (i = 0; i < nTypes; i ++) 
    { 
     // initalise FIRST the whole structure 
     // OTHERWISE the allocation is gone 
     memset(&Criteria[i],'\0',sizeof(_Criteria)); 

     // allocate CriteriaType 
     Criteria[i].CriteriaType = (_CriteriaType*)malloc(nCriteria[i] * sizeof(_CriteriaType)); 

     // initalise them 
     for (j = 0; j < nCriteria[i]; j ++) 
      memset(&Criteria[i].CriteriaType[j],'\0',sizeof(_CriteriaType)); 


    } 

} 

任何想法?我想我需要通過指針作爲參考,但我該怎麼做?

由於提前, 使用防曬回報

回答

2

它不工作的原因是C中的函數參數被複制。因此,在外部環境中nCheck = NULL,將它傳遞給CallIntAllocation函數並進行復制。 CallIntAllocation定義它的本地 nCheck的副本是malloc調用的返回值。但外部副本不更新 - 它仍然指向NULL。

最簡單的解決方案是返回新的指針值,並按照幾個人已經建議的那樣分配它。

如果您有需要修改數據結構的函數,則需要傳遞指向它們的指針而不是它們的副本,以便函數可以修改指針指向的內容。儘管你想修改的數據結構本身就是一個指針,但這裏適用同樣的原則。

因此,另一種解決方案將是CallIntAllocation採取指針到​​一個指針這將讓你修改其中的指針指向,並取消對它的引用:

CallIntAllocation(int** nCheck, int nCount) 
{ 

    *nCheck = (int*)malloc(nCount* sizeof(int)); 
    for (int j = 0; j < nCount; j++) 
     (*nCheck)[j] = 0; 
} 

和調用

CallIntAllocation(&nCheck, nCount); 

顯然在這種情況下返回一個新的指針值是明智的做法。

最後一點:如果您有它可用「 memset的」(C90但不是C89據我所知,但統一UNIX規範的一部分)可以代替你的使用「for」循環

memset(ncheck, 0, nCount); 

(這是你的函數版本,而不是那個需要int **參數的版本)

5

Criteria * 
newCriteria() { 
    Criteria *criteria = malloc(..); 
    ... 
    return criteria; 
} 

/* the caller */ 
Criteria *c1 = newCriteria(); 
Criteria *c2 = newCriteria(); 

編輯

來電者是負責調用free()

+1

爲了完整起見,你可能想說說free()駐留在調用者的責任。 – dmckee 2009-06-15 12:29:28

+0

是的,我用這種方式和工作。謝謝 – Sunscreen 2009-06-16 11:03:48

0

您可以 「迴歸」 的指針分配的內存。如果返回NULL,則意味着分配失敗。

4

你有2個可能的解決方案:

int *CallIntAllocation(int nCount) 
{ 

    int *nCheck = (int*)malloc(nCount* sizeof(int)); 
    for (int j = 0; j < nCount; j++) 
     nCheck[j] = 0; 

    return nCheck; 
} 

int* nCheck = NULL; 
int nCount = 4; 

nCheck = CallIntAllocation(nCount); 

,或者如果你想的Alloc你應該通過一個指針爲int *數組:

void CallIntAllocation(int **nCheck, int nCount) 
{ 

    *nCheck = (int*)malloc(nCount* sizeof(int)); 
    for (int j = 0; j < nCount; j++) 
     *nCheck[j] = 0; 
} 

int* nCheck = NULL; 
int nCount = 4; 

CallIntAllocation(&nCheck, nCount); 
+0

當我輸入我的答案時,您的答案不存在:/ – Pod 2009-06-15 08:45:13

+0

謝謝,我使用了退貨選項。 – Sunscreen 2009-06-16 11:02:57

3

直接回答你的問題:

int* nCheck = NULL; 
int nCount = 4; 

CallIntAllocation(&nCheck, nCount); 

nCheck[1] = 3; // allocated! 
... 

void CallIntAllocation(int** pnCheck, int nCount) 
{ 
    int* nCheck = NULL; 
    nCheck = (int*) malloc(nCount * sizeof(*nCheck)); 
    for (int j = 0; j < nCount; j++) 
     nCheck[j] = 0; 
    *pnCheck = nCheck; 
} 

但我會建議這個代替:

nCheck = CallIntAllocation(nCount); 

nCheck[1] = 3; // allocated! 
... 
int *CallIntAllocation(int nCount) 
{ 
    int * nCheck 
    nCheck = (int*) malloc(nCount * sizeof(*nCheck)); 
    for (int j = 0; j < nCount; j++) 
     nCheck[j] = 0; 
    return nCheck; 
}