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