如何在函数中动态分配内存?
How to dynamically allocate memory in a function?
假设我想动态分配内存但使用一个函数而不是在 main() 函数中。
所以我尝试这样做:
dynamAlloc(int *fPtr)
{
fPtr=malloc(cols * sizeof(*fPtr) );
if(fPtr==NULL)
{
printf("Can't allocate memory");
exit(1);
}
}
然后我意识到:即使堆上分配的内存在程序的生命周期内可用,但该内存只能由形式参数引用 fPtr
而不是实际参数(我们称之为 aPtr
).但是一旦函数退出,那段记忆就丢失了。
那么如何使用函数动态分配内存?
that memory can only be referenced by formal argument fPtr
and not the actual argument(let's call it aPtr
).
aPtr
无法在 调用 dynamAlloc()
之前向堆内存对象 表示,因为该对象尚未分配且其地址已分配给 aPtr
槽 fPtr
。此后 aPtr
do 引用堆对象。
我们只需要将aPtr
的指针地址传给dynamAlloc()
即可。因此,您需要适当的参数(实际参数)和参数(形式参数)来在函数之间传递指针 aPtr
的地址,如下所示。
So how then do I dynamically allocate memory with a function?
你做的就像你做的那样 main()
,不管指针是在 main()
还是其他函数中声明的,你只需要传递指针的地址 aPtr
到其他函数,你想在其中使用堆内存对象,比如 f.e.:
#include <stdio.h>
#include <stdlib.h>
#define cols 5
void dynamAlloc(int** fPtr);
int main()
{
int* aPtr;
dynamAlloc(&aPtr);
free(aPtr);
return 0;
}
void dynamAlloc(int** fPtr)
{
*fPtr = malloc(sizeof(*fPtr) * cols);
if(*fPtr == NULL)
{
printf("Can't allocate memory");
exit(1);
}
}
别忘了free()
堆内存!
或者像这样:
void dynamAlloc(int **fPtr)
{
*fPtr=malloc(cols * sizeof(**fPtr) ); // malloc is returning void* so in that place it would be compiler error, so pointer returned from malloc should be casted to the pointer type of the value.
if(*fPtr==NULL) // that would be a warning in gcc since NULL is a macro eq to 0, or (void*)0, it compiler version
{
printf("Can't allocate memory");
exit(1);
}
}
函数用法:
int* ptr = (int*)NULL;
dynamAlloc(&ptr);
*ptr = 1; // assign 1 to the first element, ptr is a valid pointer here
但双指针语法在某些情况下可能会变慢,最后用 return od fucntion 回答,复制那个局部指针是更好的练习。
使用宏函数更方便,像这样:
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) \
{ \
(ptr) = malloc((size_t) (n) * sizeof (ptr)[0]); \
if ((ptr) == NULL) { \
fputs("Can't allocate memory\n", stderr); \
exit(EXIT_FAILURE); \
} \
}
#define NEW(ptr) NEW_ARRAY((ptr), 1)
int main(void)
{
int *myArray;
const int myArrayLen = 100;
int i;
NEW_ARRAY(myArray, myArrayLen);
for (i = 0; i < myArrayLen; i++) {
/*...*/
}
return 0;
}
更新:
宏的目的是抽象出细节并使内存分配不易出错。对于(非宏)函数,我们必须将元素大小作为参数传递,因为当将指针传递给 void 指针类型的形式参数时,该信息会丢失:
void NewArray(void *ptr, int n, int elemSize)
{
*ptr = malloc((size_t) n * sizeof elemSize);
if (*ptr == NULL) {
fputs("Can't allocate memory\n", stderr);
exit(EXIT_FAILURE);
}
}
使用函数 NewArray 对应于第一个示例的分配调用变为
NewArray(&myArray, n, sizeof myArray[0]);
这对我们来说意义不大。
因为您需要更改指针本身 - 需要指向指针的指针
void *allocate(void **tmp, size_t size)
{
if(tmp)
{
*tmp = malloc(size);
}
return *tmp;
}
int main()
{
int *ptr;
if(!allocate((void**)&ptr, sizeof(*ptr) * 100))
{
perror("Error\n");
exit(1);
}
/* do something*/
free(ptr);
}
假设我想动态分配内存但使用一个函数而不是在 main() 函数中。
所以我尝试这样做:
dynamAlloc(int *fPtr)
{
fPtr=malloc(cols * sizeof(*fPtr) );
if(fPtr==NULL)
{
printf("Can't allocate memory");
exit(1);
}
}
然后我意识到:即使堆上分配的内存在程序的生命周期内可用,但该内存只能由形式参数引用 fPtr
而不是实际参数(我们称之为 aPtr
).但是一旦函数退出,那段记忆就丢失了。
那么如何使用函数动态分配内存?
that memory can only be referenced by formal argument
fPtr
and not the actual argument(let's call itaPtr
).
aPtr
无法在 调用 dynamAlloc()
之前向堆内存对象 表示,因为该对象尚未分配且其地址已分配给 aPtr
槽 fPtr
。此后 aPtr
do 引用堆对象。
我们只需要将aPtr
的指针地址传给dynamAlloc()
即可。因此,您需要适当的参数(实际参数)和参数(形式参数)来在函数之间传递指针 aPtr
的地址,如下所示。
So how then do I dynamically allocate memory with a function?
你做的就像你做的那样 main()
,不管指针是在 main()
还是其他函数中声明的,你只需要传递指针的地址 aPtr
到其他函数,你想在其中使用堆内存对象,比如 f.e.:
#include <stdio.h>
#include <stdlib.h>
#define cols 5
void dynamAlloc(int** fPtr);
int main()
{
int* aPtr;
dynamAlloc(&aPtr);
free(aPtr);
return 0;
}
void dynamAlloc(int** fPtr)
{
*fPtr = malloc(sizeof(*fPtr) * cols);
if(*fPtr == NULL)
{
printf("Can't allocate memory");
exit(1);
}
}
别忘了free()
堆内存!
或者像这样:
void dynamAlloc(int **fPtr)
{
*fPtr=malloc(cols * sizeof(**fPtr) ); // malloc is returning void* so in that place it would be compiler error, so pointer returned from malloc should be casted to the pointer type of the value.
if(*fPtr==NULL) // that would be a warning in gcc since NULL is a macro eq to 0, or (void*)0, it compiler version
{
printf("Can't allocate memory");
exit(1);
}
}
函数用法:
int* ptr = (int*)NULL;
dynamAlloc(&ptr);
*ptr = 1; // assign 1 to the first element, ptr is a valid pointer here
但双指针语法在某些情况下可能会变慢,最后用 return od fucntion 回答,复制那个局部指针是更好的练习。
使用宏函数更方便,像这样:
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) \
{ \
(ptr) = malloc((size_t) (n) * sizeof (ptr)[0]); \
if ((ptr) == NULL) { \
fputs("Can't allocate memory\n", stderr); \
exit(EXIT_FAILURE); \
} \
}
#define NEW(ptr) NEW_ARRAY((ptr), 1)
int main(void)
{
int *myArray;
const int myArrayLen = 100;
int i;
NEW_ARRAY(myArray, myArrayLen);
for (i = 0; i < myArrayLen; i++) {
/*...*/
}
return 0;
}
更新:
宏的目的是抽象出细节并使内存分配不易出错。对于(非宏)函数,我们必须将元素大小作为参数传递,因为当将指针传递给 void 指针类型的形式参数时,该信息会丢失:
void NewArray(void *ptr, int n, int elemSize)
{
*ptr = malloc((size_t) n * sizeof elemSize);
if (*ptr == NULL) {
fputs("Can't allocate memory\n", stderr);
exit(EXIT_FAILURE);
}
}
使用函数 NewArray 对应于第一个示例的分配调用变为
NewArray(&myArray, n, sizeof myArray[0]);
这对我们来说意义不大。
因为您需要更改指针本身 - 需要指向指针的指针
void *allocate(void **tmp, size_t size)
{
if(tmp)
{
*tmp = malloc(size);
}
return *tmp;
}
int main()
{
int *ptr;
if(!allocate((void**)&ptr, sizeof(*ptr) * 100))
{
perror("Error\n");
exit(1);
}
/* do something*/
free(ptr);
}