2014-01-25 143 views
3

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

#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中为我解析出两个命令。如果有人能够解释一点,那将会很棒。非常感谢。

+0

'char ** ch ...'...'* ch = malloc ...'...'strcpy(* ch ...'...'建立(&厘米)'... –

+0

你[需要指针指针](http://stackoverflow.com/questions/18306935/need-of-pointer-to-pointer/18307020#18307020) –

+0

想想这样;如果一个函数接受一个参数'n'并且所述函数想为'n'('n = ...')赋值一个新值,那么需要一个间接级别,也就是说,你需要一个指向'n'的指针(typeof_n *)。所有在C中的函数参数都是按值传递的,也就是复制一次。所以,既然你传给我在'char *'中,你需要一个指向其中之一的指针,即'char **'。然后你可以编写'* n = malloc(size);'。此外,'sizeof char'被定义为'1',所以在'malloc'调用中不需要这么做。 –

回答

5

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 
} 
+0

可能有助于指出用法:'build(&cm);' –

+1

'//主要必须返回void'我相信你的意思是'//主要必须返回int' –

+0

@EdS。Thanks .... – Praetorian

0

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

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

参见:Passing pointer argument by reference under C?

+1

“*你不能重新分配指针所指向的内存地址的值,因为它是按值传递的*“ - 当然可以,但是你不能指定一个新的值给指针本身,并期望它可以被调用者看到。可以为指针指向的内容分配一个新值,因为你已经有了必要的间接级别 –

+0

我想我错了;我的意思是你不能让指针指向不同的内存地址,因为它是按值传递的。当然你可以改变这个值,这就是使用指针的全部意思(双关语意思) – George

+0

这是正确的。编辑那一点,我将删除我的downvote。 –

1

如果你想在函数中的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 
} 
+0

哇,非常感谢。这真是一个干净的方式。但是,你能否详细说明为什么我们可以通过价值而不是地址来通过cm1和cm2?谢谢。 –

+0

正如我所说的,我们想要处理数据,而不是指针,所以我们将地址传递给缓冲区/数据,而不是允许函数修改指针。调用者经常声明一个本地数组,而不是调用malloc,因为它更快,并在范围结束后自动结束它的生命,从而减少忘记释放内存的机会。你看,memcpy或strcpy也是一个例子。它接受指向数据的指针,而不是指针的地址 –