gpt4 book ai didi

c - 返回指针而不是填充参数有什么含义?

转载 作者:太空宇宙 更新时间:2023-11-04 04:45:45 25 4
gpt4 key购买 nike

我正在学习 C 并且对编写函数的“最佳实践”方法很感兴趣。是返回指向动态创建的内存的指针,还是填充静态分配的内存块更可取?

请以函数allocatefpopulatef 为例

char* allocatef(size_t size){
char* result = malloc(8*size);
// do other stuff
return result;
}

我们可以通过 main 以下列方式与之交互

int main(void){
char* data = allocatef(sizeof(int));
// do stuff
free(data);
}

与这种方法相反,函数期望数据已经创建

void populatef(char* data){
// do stuff
}

并且内存是在main中静态分配的,从而避免了潜在的内存泄漏。也许一个缺点是调用者应该知道 populatef 期望的输入的确切类型。

int main(void){
char data[8 * sizeof(int)];
populatef(data);
// no need to perform a destroy
}

我找到了一些相关问题herehere ,但这些涉及 C++ 和性能方面的考虑。我对内存安全和经验丰富的 C 程序员的标准行为更感兴趣。

最佳答案

从内存安全的角度来看,并没有适合所有情况的“最佳实践”答案。用 C 编写的全部要点在于,您可以选择如何管理内存,而不是一直以相同的方式进行管理。

回到你的问题,这两个版本非常相似,因为调用者代码最终负责内存(最初分配和最终释放它),而不是让你的资源静态分配属于某个全局池管他呢。它们也不是真正相互排斥的。考虑以下替代方案:

//functions exported from module A
struct Data * allocate_data();
void initialize_data(Data *);
void deinitialize_data(Data *);
void deallocate_data(Data *);

//module B:
int main(void){
Data * allocate_data();
initialize_data(data);
//do stuff
deinitialize_data(data);
deallocate_data(data);
}

在这个版本中,我们将数据封装在抽象数据类型之后。单个模块实现对 Data 数据类型的所有操作,包括初始化、分配和释放,而调用者模块负责实际选择何时分配和释放事物。调用者模块只使用指向数据类型的指针,从不直接使用数据结构1

从这一点开始,我们可以通过添加一个额外的便利函数来同时进行分配和初始化,从而得到您的第一个解决方案。如果您通常想要 malloc 数据而不是在堆栈中分配数据,这将非常有用,并且具有使编写复杂初始化代码变得更容易的额外优势。

要获得第二个版本,只需将数据结构作为公共(public)接口(interface)的一部分即可。优点是调用者代码在堆栈上静态分配该结构,缺点是如果调用者这样做,他将负责所有分配逻辑(例如,确保分配内存的数组大小相同传递给初始化函数的数组大小)。

1 我们可以通过在 Data.h header 中做一个空的 struct Data; 声明并包含实际的 来强制执行此操作结构数据 { 字符 * 有效负载; Data.c 文件中声明。

关于c - 返回指针而不是填充参数有什么含义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21084059/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com