1

関数を介してデータを割り当てる方法を知りたいのですが、関数が返された後もデータはまだ割り当てられています。これは、基本型 (int、char**) とユーザー定義型の両方に当てはまります。以下は、コードの 2 つのスニップセットです。どちらも関数内に割り当てがありますが、戻り後に割り当てが行われます。

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


    }

}

何か案は?ポインターを参照として渡す必要があると思いますが、どうすればよいですか?

事前にありがとう、日焼け止め

4

5 に答える 5

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); 
于 2009-06-15T08:19:20.270 に答える
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;
}
于 2009-06-15T08:44:51.160 に答える
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 ** 引数を取る関数ではなく、関数のバージョン用です)

于 2009-06-15T13:36:35.357 に答える
0

割り当てられたメモリへのポインタを「返す」ことができます。NULL が返された場合は、割り当てが失敗したことを意味します。

于 2009-06-15T08:08:31.573 に答える