通过函数分配数据 (ANSI C)

发布于 2024-07-24 06:30:39 字数 1479 浏览 5 评论 0原文

我很想知道如何通过函数分配数据,并且在函数返回后数据仍然被分配。 这适用于基本类型(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));


    }

}

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

提前致谢, 防晒霜

I d love to know how I can allocate data through a function, and after the function is returned the data is still allocated. This is both for basic types (int, char**) and user defined types. Below are two snipsets of code. Both have the allocation within the function though after the return the allocation goes.

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

The same behaviour for as before though for user defined type:

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


    }

}

Any ideas? I think I need to pass the pointers as a reference, though how can i do so?

Thanks in advance,
Sunscreen

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

楠木可依 2024-07-31 06:30:39

使用返回?

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

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

编辑

调用者负责调用 free()

using return?

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

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

EDIT

the caller is responsible for calling free()

浪菊怪哟 2024-07-31 06:30:39

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

You have 2 possible solutions:

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

or you should pass a pointer to int* if you want to alloc array:

 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); 
嘿嘿嘿 2024-07-31 06:30:39

直接回答你的问题:

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

To answer your question directly:

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

but I would suggest this in stead:

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;
}
你又不是我 2024-07-31 06:30:39

它不起作用的原因是 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 afaik,但是单一 unix 规范的一部分)可以用来代替你的“for”循环

memset(ncheck, 0, nCount);

(这是你的函数版本,而不是那个版本)需要一个 int ** 参数)

The reason it is not working is that function arguments in C are copied. So, nCheck = NULL in the outside context, you pass it into the CallIntAllocation function and a copy is made. The CallIntAllocation defines it's local copy of nCheck to be the return of the malloc call. But the outer copy is not updated -- it still points at NULL.

The simplest solution is to return the new pointer value and assign it as already suggested by several people.

When you have functions that need to modify data structures, you need to pass around a pointer to them, rather than copies of them, so that the function can modify what the pointer points at. The same principle applies here, although the data structure you want to modify is itself a pointer.

So another solution would be for CallIntAllocation to take a pointer-to-a-pointer which would let you modify where the pointer points, and also dereference it:

CallIntAllocation(int** nCheck, int nCount)
{

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

and invocation

CallIntAllocation(&nCheck, nCount);

Clearly in this situation returning a new pointer value is the sensible approach.

Final point: if you have it available, "memset" (C90 but not C89 afaik, part of the single unix specification however) can be used in place of your "for" loop

memset(ncheck, 0, nCount);

(that's for your version of the function, not the one that takes an int ** argument)

渔村楼浪 2024-07-31 06:30:39

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

You can "return" the pointer to the allocated memory. If NULL is returned, that means the allocation was unsuccessful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文