从c中的函数返回两个指针

时间:2017-06-08 20:18:39

标签: c pointers

我知道你可以通过执行以下命令返回指向c中数组第一个元素的指针:

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

int *my_func(void);

int main(void)
{
    int *a;
    int i;

    a = my_func();

    for(i = 0; i < 3; i++)
    {
        printf("a[%d] = %d\n", i, a[i]);
    }

    free(a);

    return 0;
}

int *my_func(void)
{
    int *array;
    int i;

    array = calloc(3, sizeof(int));

    for(i = 0; i < 3; i++)
    {
        array[i] = i;
    }

    return array;
}

但如果我想返回两个指针而不只是一个,我试过:

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

int *my_func(int *);

int main(void)
{
    int *a;
    int *b;
    int i;

    a = my_func(b);

    for(i = 0; i < 3; i++)
    {
        printf("a[%d] = %d\n", i, a[i]);
        printf("b[%d] = %d\n", i, b[i]);
    }

    free(a);
    free(b);

    return 0;
}

int *my_func(int *array2)
{
    int *array;
    int i;

    array = calloc(3, sizeof(int));
    array2 = calloc(3, sizeof(int));

    for(i = 0; i < 3; i++)
    {
        array[i] = i;
        array2[i] = i;
    }

    return array;
}

但这个seg在printf上出错了。我通过valgrind运行它,它说在printf上有一个无效的大小4读取b,这意味着我正在用b指针做一些事情。我只是想知道什么是最好的方式来回归&#34;第二个指向数组的指针是在c?我问这个问题是因为我想这样做而不是使用全局变量(我不反对它们,因为它们有时很有用,我只是希望在可能的情况下不使用它们)。我在本网站上看到的其他问题使用静态分配的数组,但我还没有偶然发现使用动态分配的问题。提前致谢!

3 个答案:

答案 0 :(得分:3)

我可以想到三种(一半)简单的方法从C函数返回任何类型的多个项目。方法如下所述。它看起来像很多文本,但这个答案主要是代码,所以请继续阅读:

  1. 按照您的方式传入输出参数,但要正确执行。您必须为int *中的main()分配空间,然后将指针传递给my_func

    main()

    a = my_func(&b);
    

    my_func()变为:

    int *my_func(int **array2)
    {
        int *array;
        int i;
    
        array = calloc(3, sizeof(int));
        *array2 = calloc(3, sizeof(int));
    
        for(i = 0; i < 3; i++)
        {
            array[i] = i;
            (*array2)[i] = i;
        }
    
        return array;
    }
    
  2. 使您的函数分配两个指向您要分配的int数组的数组的数组。这将需要额外分配两个int指针,但可能是值得的。

    然后

    main()成为:

    int main(void)
    {
        int **ab;
        int i;
    
        ab = my_func(b);
    
        for(i = 0; i < 3; i++)
        {
            printf("a[%d] = %d\n", i, ab[0][i]);
            printf("b[%d] = %d\n", i, ab[1][i]);
        }
    
        free(ab[0]);
        free(ab[1]);
        free(ab);
    
        return 0;
    }
    
    然后

    my_func()成为:

    int **my_func(void)
    {
        int **arrays;
        int i, j;
    
        arrays = calloc(2, sizeof(int *));
        arrays[0] = calloc(3, sizeof(int));
        arrays[1] = calloc(3, sizeof(int));
    
        for(j = 0; j < 2; j++)
        {
            for(i = 0; i < 3; i++)
            {
                arrays[j][i] = i;
            }
        }
    
        return arrays;
    }
    
  3. 返回结构或结构指针。您需要定义结构,并决定是否要返回结构本身,新分配的指针,或者将其作为指针传递,并为其填充my_func()

    结构定义如下所示:

    struct x
    {
        int *a;
        int *b;
    }
    

    然后,您可以将当前函数重新设置为以下三个选项之一:

    1. 直接传递结构(不推荐用于一般用途):

      int main(void)
      {
          struct x ab;
          int i;
      
          ab = my_func();
      
          for(i = 0; i < 3; i++)
          {
              printf("a[%d] = %d\n", i, ab.a[i]);
              printf("b[%d] = %d\n", i, ab.b[i]);
          }
      
          free(ab.a);
          free(ab.b);
      
          return 0;
      }
      
      struct x my_func(void)
      {
          struct x ab;
          int i;
      
          ab.a = calloc(3, sizeof(int));
          ab.b = calloc(3, sizeof(int));
      
          for(i = 0; i < 3; i++)
          {
              ab.a[i] = i;
              ab.b[i] = i;
          }
      
          return ab;
      }
      
    2. 返回一个指向动态分配结构的指针(这通常是一个非常好的选项):

      int main(void)
      {
          struct x *ab;
          int i;
      
          ab = my_func();
      
          for(i = 0; i < 3; i++)
          {
              printf("a[%d] = %d\n", i, ab->a[i]);
              printf("b[%d] = %d\n", i, ab->b[i]);
          }
      
          free(ab->a);
          free(ab->b);
          free(ab);
      
          return 0;
      }
      
      struct x *my_func(void)
      {
          struct x *ab;
          int i;
      
          ab = malloc(sizeof(struct x));
          ab->a = calloc(3, sizeof(int));
          ab->b = calloc(3, sizeof(int));
      
          for(i = 0; i < 3; i++)
          {
              ab->a[i] = i;
              ab->b[i] = i;
          }
      
          return ab;
      }
      
    3. main()中分配结构,并通过传入的指针将其填入my_func。如果传入my_func指针,NULL将分配结构,通常会使用此选项,否则它将返回您传入的任何内容。此处显示的my_func版本具有简单来说没有返回值:

      int main(void)
      {
          struct x ab;
          int i;
      
          my_func(&ab);
      
          for(i = 0; i < 3; i++)
          {
              printf("a[%d] = %d\n", i, ab.a[i]);
              printf("b[%d] = %d\n", i, ab.b[i]);
          }
      
          free(ab.a);
          free(ab.b);
      
          return 0;
      }
      
      void my_func(struct x *ab)
      {
          int i;
      
          ab->a = calloc(3, sizeof(int));
          ab->b = calloc(3, sizeof(int));
      
          for(i = 0; i < 3; i++)
          {
              ab->a[i] = i;
              ab->b[i] = i;
          }
      
          return;
      }
      
  4. 对于此处显示的所有示例,请不要忘记更新文件顶部的my_func声明,但我相信如果您忘记,任何合理的编译器都会提醒您。

    请记住,这些只是我立刻从脑中拉出来的三个选项。虽然它们可能会覆盖99%的任何用例,但您可能很快就会遇到这些用例,但其中有很多(可能有很多)其他选项。

答案 1 :(得分:1)

函数参数是其局部变量。函数处理所提供参数的值的副本。

您可以通过以下方式想象您的函数定义及其调用

a = my_func(b);


int *my_func( /* int *array2 */ )
{
    int *array2 = b;
    //...
}

因此,函数内局部变量array2的任何更改都不会影响原始参数b

对于这样的函数定义,你必须通过引用传递参数,该函数应该被声明为

int *my_func( int **array2 );
                  ^^

有很多方法可以实现这个功能。您可以定义两个指针的结构,例如

struct Pair
{
    int *a;
    int *b;
};

并将其用作函数的返回类型

struct Pair my_func( void );

另一种方法是向函数传递一个指向原始指针的指针数组。

该功能可以看起来像示范程序中所示。

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

size_t multiple_alloc( int ** a[], size_t n, size_t m )
{
    for ( size_t i = 0; i < n; i++ ) *a[i] = NULL;

    size_t k = 0;

    for ( ; k < n && ( *a[k] = malloc( m * sizeof( int ) ) ) != NULL; k++ )
    {
        for ( size_t i = 0; i < m; i++ ) ( *a[k] )[i] = i;
    }

    return k;
}

#define N   2
#define M   3

int main(void) 
{
    int *a;
    int *b;

    multiple_alloc( ( int ** [] ) { &a, &b }, N, M );

    if ( a )
    {
        for ( size_t i = 0; i < M; i++ ) printf( "%d ", a[i] );
        putchar( '\n' );
    }

    if ( b )
    {
        for ( size_t i = 0; i < M; i++ ) printf( "%d ", b[i] );
        putchar( '\n' );
    }

    free( a );
    free( b );

    return 0;
}

程序输出

0 1 2 
0 1 2 

答案 2 :(得分:0)

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

int *my_func(int **);

int main(void)
{
    int *a;
    int *b;
    int i;

    b=(int *)malloc(sizeof(int));

    a = my_func(&b);


    for(i = 0; i < 3; i++)
    {
        printf("a[%d] = %d\n", i, a[i]);
        printf("b[%d] = %d\n", i, b[i]);
    }

    free(a);
    free(b);

    return 0;
}

int *my_func(int **array2)
{
    int *array;
    int i;


    array = calloc(3, sizeof(int));
    *array2 =calloc(3,sizeof(int));

    for(i = 0; i < 3; i++)
    {
        array[i] = i;
        *((*array2)+i)=i;//or (*array2)[i]

    }

    return array;
}

通过引用传递指针。因为它与操作整数块的逻辑相同,所以需要传递一个指向它的指针。同样,要操纵指针,你必须传递一个指向它的指针(即指向指针的指针)。