【问题标题】:Allocate data through a function (ANSI C)通过函数分配数据 (ANSI C)
【发布时间】:2009-06-15 07:53:43
【问题描述】:

我很想知道如何通过函数分配数据,并且在函数返回后数据仍然被分配。这适用于基本类型(int、char**)和用户定义类型。下面是两个代码片段。两者都在函数内进行分配,尽管在返回之后分配去了。

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


    }

}

有什么想法吗?我想我需要将指针作为参考传递,但我该怎么做?

提前致谢, 防晒霜

【问题讨论】:

    标签: c pointers malloc c89


    【解决方案1】:

    使用返回?

    Criteria *
    newCriteria() {
       Criteria *criteria = malloc(..);
       ...
       return criteria;
    }
    
    /* the caller */
    Criteria *c1 = newCriteria();
    Criteria *c2 = newCriteria();
    

    编辑

    调用者负责调用free()

    【讨论】:

    • 为了完整起见,您可能想说几句关于驻留在调用者中的 free() 的责任。
    【解决方案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); 
    

    【讨论】:

    • 当我输入我的答案时,你的答案不存在:/
    • 谢谢,我使用了退货选项。
    【解决方案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;
    }
    

    【讨论】:

    • 感谢 Pod,我这样做了(分别返回 int* 和 _Criteria*)并且工作正常。
    【解决方案4】:

    它不起作用的原因是复制了 C 中的函数参数。因此,在外部上下文中,nCheck = NULL,您将它传递给 CallIntAllocation 函数并制作一个副本。 CallIntAllocation 将 nCheck 的 local 副本定义为 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 afaik,不过是单一 unix 规范的一部分)可以用来代替“for”循环

    memset(ncheck, 0, nCount);
    

    (这是您的函数版本,而不是采用 int ** 参数的版本)

    【讨论】:

    • 谢谢大家,谢谢jmtd。我想我可以通过 memset 再次初始化我的 Struct:memset(&Criteria, 0x00, sizeof(Criteria));
    【解决方案5】:

    您可以“返回”指向已分配内存的指针。如果返回NULL,则表示分配不成功。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-21
      • 2011-12-07
      • 2013-10-08
      • 2017-09-06
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多