2009-06-15 15 views
1

関数を使ってデータをどのように割り当てることができ、関数が返された後でもデータは割り当てられています。これは、基本型(int、char **)とユーザー定義型の両方に適用されます。以下はコードの2つのスナップショットです。割り当ての返却後も両方とも関数内で割り当てが行われます。関数(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仕様の一部)は、あなた(ループ

memset(ncheck, 0, nCount); 

「について」の代わりに使用することができますそれはあなたの関数のバージョンで、int **引数をとるものではありません)

+0

ありがとう、感謝jmtd。そして私はmemsetによって再び構造体を初期化できると思います:\t memset(&Criteria、0x00、sizeof(Criteria)); – Sunscreen

5

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

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

EDIT

は、呼び出し側は(無料の呼び出しに責任がある)

+1

完全性のために、呼び出し側に存在するfree()の責任についていくつか言いたいことがあります。 – dmckee

+0

はい私はこの方法で使用し、働いた。 Thanks – Sunscreen

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); 

たり、配列をアロケーションしたい場合は、* 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

+0

ありがとう、私は戻り値のオプションを使用しました。 – Sunscreen

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; 
} 
+0

ありがとうポッド、私はこのように(int *と_Criteriaをそれぞれ返す)して動作します。 – Sunscreen

関連する問題