【问题标题】:return multiple values from a function in C [duplicate]从C中的函数返回多个值[重复]
【发布时间】:2014-01-25 07:03:20
【问题描述】:

我最初的问题是我想编写一个可以返回两个值的函数。我知道我可以通过将两个参数的地址传递给函数来做到这一点,并直接在该函数内计算它们的值。但是在做实验时,会发生一些奇怪的事情。我在函数中得到的值无法保存到主函数中:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void build(char *ch){
   ch = malloc(30*sizeof(char));
   strcpy(ch, "I am a good guy");
}

void main(){
   char *cm;
   build(cm);
   printf("%s\n", cm);
}

上面的程序只是打印出一些垃圾。所以我想知道这里出了什么问题。最终,我想要像 parse(char **argv, char **cmd1, char **cmd2) 这样的东西,它可以从原始命令 argv 中为我解析出两个命令。如果有人能解释一下,那就太好了。非常感谢。

【问题讨论】:

  • char **ch... ... *ch = malloc... ... strcpy(*ch... ... build(&amp;cm) ...
  • 这样想;如果一个函数接受一个参数 n 并且该函数想要为 n (n = ...) 分配一个新值,则需要一个间接级别,即,您需要一个指向 n (typeof_n*) 的指针。 C 中的所有函数参数都是按值传递的,即复制。所以,既然你传入了char*,你需要一个指向其中之一的指针,即char**。然后你可以写*n = malloc(size);。此外,sizeof char 被定义为1,因此在您的malloc 调用中不需要它。

标签: c function return-value


【解决方案1】:

build() 按值获取指针 ch,即将指针的副本传递给函数。因此,当函数退出时,您对该值所做的任何修改都会丢失。由于您希望对指针的修改在调用者的上下文中可见,因此您需要将指针传递给指针。

void build(char **ch){
   *ch = malloc(30*sizeof(char));
   strcpy(*ch, "I am a good guy");
}

此外,您不需要将指针传递给函数,因为您需要返回多个值。另一种选择是创建一个struct,其中包含您希望作为成员返回的值,然后返回上述struct 的实例。如果值是相关的并且将它们打包在一起很有意义,我会推荐这种方法而不是第一种方法。


这是修复错误后重新列出的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void build(char **ch){
   *ch = malloc(30 * sizeof(char));
   strcpy(*ch, "I am a good guy");
}

int main() {     // main must return int
   char *cm;
   build(&cm);   // pass pointer to pointer
   printf("%s\n", cm);
   free(cm);     // free allocated memory
   return 0;     // main's return value, not required C99 onward
}

【讨论】:

  • 可能有助于指出用法:build(&amp;cm);
  • // main must return void我相信你的意思是// main must return int
【解决方案2】:

如果要在函数内部进行malloc,则需要将地址传递给外部指针,因为函数内部的ch只是一个局部变量,更改它不会影响外部的cm变量

void build(char **ch){
   *ch = malloc(30*sizeof(char));
   strcpy(*ch, "I am a good guy");
}

void main(){
   char *cm;
   build(&cm);
   printf("%s\n", cm);
}

但最好不要在函数内部malloc,而只需将您想要的内容写入指针指向的区域即可。当您需要提供缓冲区以在 C 中获取数据时,这是常用的方式。这样,用户可以选择自己分配内存,或者只使用本地缓冲区,之后不需要像您一样释放内存'刚刚忘记了你的例子

void build(char *ch){
   strcpy(ch, "I am a good guy");
}

void main(){
   char *cm1;
   cm1 = malloc(30*sizeof(char));
   build(cm1);
   printf("%s\n", cm1);

   char cm2[30];
   build(cm2);

   printf("%s\n", cm2);   
   free(cm1);           // don't forget this
}

【讨论】:

  • 哇,非常感谢。这确实是一种干净的方式。但是你能详细说明为什么我们可以通过值而不是地址传递 cm1 和 cm2 吗?谢谢。
  • 正如我所说,我们要处理数据,而不是指针,所以我们将地址传递给缓冲区/数据,而不是允许函数修改指针。调用者经常声明一个本地数组而不是调用 malloc,因为它更快并且在作用域结束后自动结束它的生命,减少了像你的情况一样忘记释放内存的机会。你看,memcpy 或 strcpy 也是一个例子。它接受指向数据的指针,而不是指针的地址
【解决方案3】:

这是因为在 C 中,不能重新分配指针的内存地址,因为它是按值传递的。

如果你真的想这样做,你必须将指针的地址传递给构建函数。

见:Passing pointer argument by reference under C?

【讨论】:

  • "您不能重新分配指针指向的内存地址的值,因为它是按值传递的。" - 当然可以。但是,您不能为指针本身分配新值并期望它对调用者可见。您可以为指针 所指的内容分配一个新值,因为您已经具备了必要的间接级别。
  • 我想我用错了;我的意思是你不能让指针指向不同的内存地址,因为它是按值传递的。当然你可以改变值,这就是使用指针的全部意义(双关语)
  • 那是正确的。编辑那一点,我会删除我的反对票。
  • 完成。 (加上这个额外的评论,因为上面的评论不够长,无法发布......)
猜你喜欢
  • 2011-04-19
  • 2022-01-20
  • 1970-01-01
  • 2016-03-16
  • 2016-09-26
  • 2015-07-07
  • 1970-01-01
相关资源
最近更新 更多