C - 将数组作为函数参数返回

时间:2017-01-15 16:14:20

标签: c arrays function

我试图传递一个角色阵列' p'一个函数' func'并将其复制到另一个论点' arg'在功能里面。但是,阵列没有被复制,尽管我能够修改' p'在' func'并且能够验证主要功能的变化,' res'不会使用' p'中的值进行复制。它打印空白。我不确定自己犯了什么错误。

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

void func(char *c, int size, char *res)
{
        int i;
        printf("Printing c in func...\n");
        for(i=0;i<size;i++) {
                printf("%c",c[i]);
        }
        printf("\n");
        c[2] = 'j';
        res = c;
}

int main(void)
{
        char c[5]={'h','e','l','l','o'};
        char *p,*arg;
        int i, size = 5;
        p=c;
        arg = (char*)malloc(size);
        func(p,size,arg);
        printf("Printing p in main...\n");
        for(i=0;i<size;i++) {
                printf("%c",p[i]);
        }
        printf("\n");
        printf("Printing arg in main...\n");
        for(i=0;i<size;i++) {
                printf("%c",arg[i]);
        }
        printf("\n");

        return 0;
}

输出:

Printing c in func...
hello
Printing p in main...
hejlo
Printing arg in main...

2 个答案:

答案 0 :(得分:2)

在C中,函数的参数按值传递。函数执行结束后,位置resc不存在。请注意,您正在进行的更改是使用指针本身而不是位置指针指向的。因此res无法看到对main的任何更改。

要使更改对main可见,您需要将arg的地址传递给函数func

func签名应为

void func(char *c, int size, char **res) ;  

来自main的来电应为

func(p, size, &arg);  

同时将作业res = c;中的作业*res = c;更改为func

在这种情况下,您传递的是指针arg的地址,并且对res所指向的位置进行了更改。 res指向reg的地址,因此res指向的地址所做的任何更改都将保留并main可见。

现在看看它是如何工作的。最初在建议的更改后调用您的函数func时:

      +-----------+                (0x300 is a random memory location)
      |           |
arg   |   0x300   | <---------+
      |           |           |
      +-----------+           |
        0x100                 |
                              |
                              |
      +-----------+           |
      |           |           |
res   |   0x100   +-----------+
      |           |
      +-----------+
         0x200

当您将c分配给*res(别名为reg)时,*resreg指向c分的位置至。假设字符hello存储在0x500,则*res = creg指向0x500

                                                            Array c (in main)
      +-----------+                                  +-----+-----+-----+-----+-----+------+
      |           +--------------------------------->+ 'h' | 'e' | 'j' | 'l' | 'o' | '\0' |
arg   |   0x500   | <---------+                      +-----+-----+-----+-----+-----+-------                                      
      |           |           |                       0x500  .... 
      +-----------+           |
        0x100                 |
                              | *res = c
                              |
      +-----------+           |
      |           |           |
res   |   0x100   +-----------+
      |           |
      +-----------+
         0x200

答案 1 :(得分:1)

在C指针中,按值对函数进行篡改,所以在你的函数中:

void func(char *c, int size, char *res)

res是与传递给它的指针完全不同的对象

func(p, size, arg);

它与arg不同,但它指向(仅指向)与传递给此函数时指向的arg相同的位置。

因此分配

res = c;

疯狂的内部函数只更改本地指针(函数内部的一个)。如果你做了

*res = *c;

然后指向的内存将被更改,并且从函数外部可以看到,因为原始指针的内存指向 相同< / strong>作为res指向的那个。这也是将'j'写入c[2]更改原始数组的原因:

c[2] = 'j'; /* note: this is same as *(c + 2) = 'j'; and this is why it works - you
               are using memory pointed to by pointer */

如果您需要更改指针本身,则需要将地址传递给该指针:

void func(char *c, int size, char **res)