在某些函数(例如* scanf variants)中,有一个参数为结果占用了一个内存空间。您也可以在返回地址的地方编写代码。有什么好处,为什么以这种奇怪的方式设计功能?
实施例
void process_settings(char* data)
{
.... // open file and put the contents in the data memory
return;
}
VS
char* process_settings()
{
char* data = malloc(some_size);
.... // open file and load it into data memory
return data;
}
答案 0 :(得分:3)
使用一种方法而不是另一种方法的决定取决于你打算做什么。
实施例
如果要修改函数内部的数组并维护原始数组中的修改,则应使用第一个示例。
如果要创建自己的数据结构,则必须处理所有操作。如果你想创建一个新结构,你应该在函数内部分配内存并返回指针。第二个例子。
如果你想"返回"函数中的两个值,如向量和向量的长度,并且您不想为此创建结构,您可以返回向量的指针并传递一个int指针作为函数的参数。这样你就可以修改函数内部的int值,也可以在外面使用它。
char* return_vector_and_length(int* length);
答案 1 :(得分:3)
好处是您可以保留函数的返回值以进行错误检查,状态指示器等,并使用输出参数实际发送回数据。实际上,使用此模式,您可以发回任何数量的数据以及返回值,这可能非常有用。当然,通过多次调用该函数(例如,在循环中调用scanf
来验证用户输入),您每次都不必malloc
。
有效使用此模式的最佳示例之一是函数strtol
,它将字符串转换为long
。
该函数接受指向字符的指针作为其参数之一。将char
本地声明为endptr
并将其地址传递给函数是很常见的。如果能够,该函数将返回转换后的数字,但如果没有,它将返回0
以指示失败但是将传入的字符指针设置为非遇到导致失败的数字字符。
然后,您可以报告该特定字符的转换失败。
这比使用全局错误指标更好的设计;考虑多线程程序。如果您要调用可能在多个线程中失败的函数,则使用全局错误指示符可能是不合理的。
你提到函数应该负责自己的内存。好吧,scanf
并不存在创建内存来存储扫描值。存在从输入缓冲区扫描值。该功能的职责非常明确,并不包括分配空间。
返回malloc
指针也不合理。但是程序员应该谨慎,free
当他们使用它时返回指针。
答案 2 :(得分:0)
例如,假设您希望将流程设置存储在内存中的特定位置。对于第一个版本,您可以将其写为process_settings(output_buffer + offset);
。如果只有第二个版本,你将如何做到这一点?如果它是一个非常大的阵列会对性能产生什么影响?或者,假设您正在编写一个多线程应用程序,其中所有线程始终调用malloc()
将使它们在堆上进行争夺并序列化程序,因此您需要预先分配所有缓冲区吗? / p>
在某些情况下,你的直觉是正确的:在可以对内存映射文件的现代操作系统中,返回指向文件内容的指针比标准库的历史编写方式更有效,并且这就是glib
的作用。有时在堆上分配所有缓冲区有助于避免粉碎堆栈的缓冲区溢出。
重要的一点是,如果你有第一个版本,你可以通过调用malloc
然后将缓冲区作为dest参数传递给第二个版本。但是,如果只有第二个,则不能在不复制整个数组的情况下实现第一个。