一个返回字符数组的C函数 Vs 一个使用2个字符数组的函数

3

我是一名C语言初学者,如果我的问题太过简单,请见谅。

解决这个问题的最有效方法是什么:假设你有一个字符数组ORIG,经过处理后,你应该有一个新的字符数组DEST。因此,如果我想为此创建一个函数,最好的方法是:

  1. 一个只接受一个char数组参数(参数ORIG)并返回一个char数组DEST的函数;或者
  2. 一个无返回值的函数,它接受两个char数组参数,并根据需要更改DEST。

谢谢!


在C语言中,“返回数组”的函数并不像其他语言那样容易实现,因此1很少有用。这种情况通常是通过将原始缓冲区和目标缓冲区传递到函数中来完成的,然后函数会填充目标缓冲区。 - Lee Daniel Crocker
4个回答

4
这在很大程度上取决于您的函数性质。
在第一种情况下,函数必须为结果分配存储空间(或返回指向某些静态对象的指针,但这不是线程安全的)。例如,对于像POSIX的strdup()这样复制字符串的函数,这可能是正确的做法。这也意味着调用者在不再需要结果时必须使用free()
第二种情况要求调用者提供存储空间。在C语言中,这通常是做这些事情的惯用方式,因为在这种情况下,调用者可以直接编写:
char result[256];
func(result, "bla bla");

因此,使用一个自动对象来保存结果。这也有好处,你可以使用实际的返回值来表示错误。


1
使用返回值来表示错误是一个很好的点,也可以说是在函数外创建存储空间的最佳原因。 - Spoonless
“arguably” ;) 我认为选择这种方式时,提供存储的灵活性通常同样重要 ;) - user2371524

1
在选项1中,您需要动态分配(malloc)输出数组。这意味着存在内存泄漏的可能性。在选项2中,输出数组已经为您提供,因此没有泄漏的机会,但是有可能输出数组大小不足,在写入时会发生缓冲区溢出。
两种方法都可以接受,其中一种与另一种相比可能会有小的性能差异,但最终取决于您的选择。
个人而言,作为一个谨慎的程序员,我会选择选项3:
/* Returns 0 on success, 1 on failure
   Requires : inputSize <= outpuSize
              input != output
              input != null
              output != null 
*/
int DoStuff (char* output, size_t outputSize, char* input, size_t inputSize);

抱歉,如果这不是正确的C语言代码,因为已经过了几十年 :)

(根据Felix Palmen的建议进行了编辑。)


不一定需要指定大小,但给出提示是个好主意。还有两件事:1)使用 size_t 表示大小;2)(有争议的)将 输出 参数放在第一位,因为大多数 C 函数都是这样做的。 - user2371524
抱歉,我已经很久没有写 C 了,但我同意你们两个的观点,我没有意识到 C 有 size_t。 - Code Gorilla

1

这两种方法都是有效的,但我建议使用后者,因为它意味着您可以将内容加载到任何内存块中,而返回的数组必须在堆上,并按设计进行释放。 再次强调,这两种方法都是有效的,这只是一个指导方针。通常应根据情况来确定应该采取什么措施。


1

这要看情况而定,如果你知道DEST的长度与ORIG的长度相同,我会选择第二种方法,因为你不需要在函数内动态分配dest的内存(并记得在函数外释放它)。 如果长度不同,你必须动态分配内存,有两种方法: 1. 像你的第一种方法一样-在C语言中返回数组,你必须分配一个新的数组并返回它的地址(指针)。 2. 函数可以接收两个参数,一个是ORIG,另一个是RES的双指针,因为函数接收了一个双指针,它可以在内部分配一个数组,并通过参数返回它。 1-从代码角度来说更加“干净”,从用户体验角度来说更容易使用(用户是调用者)

祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接