是返回一个结构指针好还是修改指针参数好?

2013-01-12 10:56:52 +08:00
 Sherlockhlt
在C中函数返回数据的时候,一般可以通过返回一个结构指针或者直接设置一个指针参数,把这个指针参数指向要返回的数据。
我经常看到有些API(比如Openssl)都是两种返回方式都实现的,这样子会不会很冗余?
哪一种方式更好?
3964 次点击
所在节点    程序员
15 条回复
Radeon
2013-01-12 11:02:58 +08:00
库函数不要返回自己"malloc"出来的数据,原因是客户代码和库函数有可能不使用一致的内存管理器

如果是自己的代码内部,又都使用标准的C的malloc(),可以用第一种方式返回数据
Radeon
2013-01-12 11:10:49 +08:00
补充一下,有时候库函数确实需要返回大小在调用前不确定的数据,由于大小不确定,所以调用方很难提前分配

方法有二
1. 提供一个查询函数,查询返回数据有多大,还是由调用方分配
2. 提供一个释放内存的函数,这样库函数可以安心用自己的内存管理器来动态分配内存
Sherlockhlt
2013-01-12 11:49:34 +08:00
@Radeon
什么情况下会使用不一致的内存管理器呢?
Radeon
2013-01-12 11:54:56 +08:00
@Sherlockhlt 原因有好几种
1. 标准的malloc()不够优化。对于openssl这种lib来说,自己搞一套内存管理器,甚至关键路径用汇编都很正常
2. 库函数已经静态链接某一特定版本的malloc()了,用户代码自己可以用另一个版本。一个进程里存在两套以上的内存管理器互不干扰,虽然C语言的入门书不会提,但是是完全正常的。而且实际中的复杂应用中也很常见
3. 库函数实际上是OS的API。Kernel里的内存管理器和User land的自然不一样,想一样也不可能
Radeon
2013-01-12 11:59:27 +08:00
很多C语言的初学者以为malloc()是最底层的函数之一。很遗憾,不是。malloc()只是OS提供的user land内存管理API的二道贩子而已
Soichir
2013-01-13 10:18:25 +08:00
lz能不能举一个两种方式的例子。
为什么我觉着 返回一个结构指针 和 修改指针 参数是一个意思。。。
thx
bombless
2013-01-13 10:47:07 +08:00
bombless
2013-01-13 10:48:36 +08:00
大约是上贴这个意思吧……手贱直接点了回复……
Sherlockhlt
2013-01-13 11:13:14 +08:00
@Soichir
@bombless

对,就是这个意思。不过有一点我不是很明白,为什么要
void modify_pointer(int **p){
*p = (int*)malloc(sizeof(int));
}
而不是
void modify_pointer(int *p){
p = (int*) malloc(sizeof(int));
}
yuzhigang33
2013-01-13 12:36:14 +08:00
@Sherlockhlt 第二个改变不了指针的值啊,形参。如果在外面定义int *p1 = null; 把p1传进去,出来后,p1还是null。
Sherlockhlt
2013-01-13 12:45:21 +08:00
@yuzhigang33
原来如此
xuan_lengyue
2013-01-13 13:07:52 +08:00
这玩意用Objective-C来类比可能更好解释。
Objective-C当中一般alloc的变量都是需要在稍后手动release的,
而非alloc函数生成的变量一般就无需稍后手动release。
其实就是约定俗成的,这块内存到底谁来管的问题。
bombless
2013-01-15 10:25:57 +08:00
看了一下回复,我想到一点:返回值最好用来指示操作是否成功,因此最好在参数列表中留一个指针的指针用于返回一个缓冲区地址。


这关键还是代码风格的问题:有的 C 函数是没有参数列表或者说参数列表是一个 void 。
对这样的函数最自然的做法就是用返回值来指示操作是否成功。
为了与这样的函数统一,最好所有的函数都用返回值来指示操作是否成功。


对于有一些函数只需要返回一个缓冲区地址的函数,可以用返回空指针的做法来指示操作失败;但如果剩余的 API 函数高度统一,那么这个函数就成为了特例并成为一个污点。


返回空指针的做法还有一个很大的缺陷:它不符合一些编译系统的语义,所以无法让原来的API自然的扩展到一些新平台,从而在 API 的移植上留下污点。而许多平台例如 CORBA、OpenCl 上的 API 都有这样的需求。

例如我很赞赏的 Scala ,虽然它也有空引用,但许多时候类似的语义靠 Option 类来表达,因此它就在与返回空指针来指示操作失败的做法上需要协调一下,在美学上难免带来一些招致争执的考量。
xdeng
2013-01-15 10:43:04 +08:00
如果是制作成dll库 或者lib库 就需要提供dll库 或者lib库 自己内部的free
最明显的是vc debug版的free 和 release版的free 不能通用。
xdeng
2013-01-15 10:44:20 +08:00
看具体情况的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/57362

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX