函数返回字符串,风格好吗?


11

在我的C程序中,我经常需要一种方法来对我的ADT进行字符串表示。即使我不需要以任何方式将字符串打印到屏幕上,使用这种调试方法也很简洁。因此,经常会出现这种功能。

char * mytype_to_string( const mytype_t *t );

我实际上意识到我在这里有(至少)三个选项来处理返回字符串的内存。

备选方案1:将返回字符串存储在函数的静态char数组中。除了每次调用都会覆盖该字符串外,我不需要太多思考。在某些情况下这可能是个问题。

备选方案2:使用函数内部的malloc在堆上分配字符串。真的很整洁,因为我那时无需考虑缓冲区的大小或覆盖的问题。但是,我确实必须记得在完成操作后将字符串free(),然后还需要分配一个临时变量,以便可以释放。然后堆分配实际上比堆栈分配要慢得多,因此如果在循环中重复进行,则将成为瓶颈。

备选方案3:将指针传递到缓冲区,然后让调用方分配该缓冲区。喜欢:

char * mytype_to_string( const mytype_t *mt, char *buf, size_t buflen ); 

这给呼叫者带来了更多的努力。我还注意到,该替代方案在参数顺序方面为我提供了另一个选择。我应该首先讨论哪个论点?(实际上有六种可能性)

那么,我该选择哪个呢?为什么?C开发人员中是否存在某种不成文的标准?


3
只是注意,大多数操作系统都使用选项3-调用者无论如何都分配缓冲区。告诉缓冲区指针和容量;被调用者填充缓冲区,如果缓冲区不足,则返回字符串实际长度。示例:sysctlbyname在OS X和iOS中
rwong

Answers:


11

我最常看到的方法是2和3。

用户提供的缓冲区实际上非常易于使用:

char[128] buffer;
mytype_to_string(mt, buffer, 128);

虽然大多数实现都会返回使用的缓冲区数量。

当使用动态链接库时,它们可能使用不同的运行时(和不同的堆),因此选项2会更慢并且很危险。因此,您无法释放已在另一个库中分配的内容。然后,这需要一个free_string(char*)函数来处理。


谢谢!我认为我也最喜欢替代方案3。但是我希望能够做类似的事情:printf("MyType: %s\n", mytype_to_string( mt, buf, sizeof(buf));因此,我不想返回使用的长度,而是返回指向字符串的指针。动态库注释非常重要。
奥伊斯坦Schønning -约翰森

这不是sizeof(buffer) - 1为了满足\0终结者吗?
Michael-O

1
@ Michael-O否null项不包括在缓冲区大小中,这意味着可以放入的最大字符串比传递的大小小1。这是安全字符串在标准库中起作用的模式snprintf
棘轮怪胎

@ratchetfreak感谢您的澄清。很好地用这种智慧来扩展答案。
Michael-O

0

#3的其他设计思路

如果可能,还请mytype在与.h相同的.h文件中提供所需的最大大小mytype_to_string()

#define MYTYPE_TO_STRING_SIZE 256

现在,用户可以进行相应的编码。

char buf[MYTYPE_TO_STRING_SIZE];
puts(mytype_to_string(mt, buf, sizeof buf));

订购

首先,数组的大小允许使用VLA类型。

char * mytype_to_string( const mytype_t *mt, size_t bufsize, char *buf[bufsize]); 

单一维度的重要性不高,但具有2个或更大的维度时则很有用。

void matrix(size_t row, size_t col, double matrix[row][col]);

我记得在下一个C语言中,首选阅读尺寸是第一个惯用法。需要查找该参考文献...。


0

作为@ratchetfreak出色答案的补充,我要指出,替代方法#3遵循与标准C库函数相似的范例/模式。

例如,strncpy

char * strncpy ( char * destination, const char * source, size_t num );

遵循相同的范例将有助于减轻新开发人员(甚至您未来的自我)在需要使用您的功能时的认知负担。

与您的帖子唯一的区别destination是C库中的参数倾向于在参数列表中首先列出。所以:

char * mytype_to_string( char *buf, const mytype_t *mt, size_t buflen ); 

-2

除了您提议做的是一种不好的代码气味这一事实外,替代3听起来对我来说最好。我也认为像@ gnasher729一样,您使用的语言也不正确。


您究竟认为代码气味是什么?请详细说明。
绿巨人

-3

老实说,您可能希望切换到其他语言,在这种语言中,返回字符串并不复杂,工作量大且容易出错。

您可以考虑使用C ++或Objective-C,使99%的代码保持不变。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.