【问题标题】:assignment after function returning array of pointers函数返回指针数组后的赋值
【发布时间】:2012-06-27 03:23:32
【问题描述】:

这是我感到困惑的代码。如果有人更正此代码会很有帮助吗?

 int (*(x)())[2];
int main()
{
   int (*(*y)())[2]=x;

   x();
   return 0;
}

int (*(x)())[2]
{
  int **str;
  str=(int*)malloc(sizeof(int)*2);
  return str;
}

x 返回时如何分配指针数组?是使用 malloc only 解决方案吗?

提前致谢

【问题讨论】:

  • int **arr = x(); 有什么问题?
  • 您到底想完成什么?在 main 中,y 是一个由 2 个指针组成的数组,这些指针指向返回 int 并采用任意参数的函数的指针。然后给它分配一个(未定义的)变量 x。 WTH?!
  • real 解决方案可能首先不返回指针数组。而是将指向数组内容的指针作为参数并将其填充到您的函数中。
  • "这是我弄糊涂的代码" 开,难怪!这段代码是为了迷惑人而写的:)
  • 我觉得这更像是编程语言的作业。

标签: c


【解决方案1】:

尚不完全清楚您要完成什么,因此我将介绍不止一种可能性。

首先,复习一下如何在 C 中读写复杂的声明:

记住()[] 的优先级高于一元*,所以*a[] 是一个指针数组,而(*a)[] 是一个指向数组;同样,*f() 是一个返回指针的函数,而(*f)() 是一个指向函数的指针

当你试图阅读一个毛茸茸的声明时,从最左边的标识符开始,然后记住上面的规则。因此,

 int (*(x)())[2];

读作

        x            -- x
       (x)           -- x
       (x)()         -- is a function
      *(x)()         -- returning a pointer
     (*(x)())[2]     -- to a 2-element array
 int (*(x)())[2]     -- of int

在这种情况下,x 周围的括号是多余的,可以删除:int (*x())[2];

以下是如何编写和使用这样的函数:

int (*x())[2]
{
  int (*arr)[2] = malloc(sizeof *arr);  // alternately, you could simply write
  return arr;                           // return malloc(sizeof (int [2]));
}                                       // type of *arr == int [2]

int main(void)
{
  int (*p)[2] = NULL;                   // alternately, you could write
  ...                                   // int (*p)[2] = x();
  p = x();
  ...
  free(p);
}

注意arrpx() 的声明看起来都一样——它们都符合int (*_)[2]; 的模式。 这很重要。如果您将一件事声明为T (*p)[N],将另一件事声明为T **q,那么它们的类型不同并且可能不兼容。指向T 数组的指针与指向T 的指针的类型不同。

如果您的目标是创建一个指向返回int函数 的指针数组,那么您的类型将类似于int (*f[2])();,其内容为

      f          -- f
      f[2]       -- is a 2-element array
     *f[2]       -- of pointers
    (*f[2])()    -- to functions
int (*f[2])();   -- returning int

看起来像下面这样:

int foo() {...}
int bar() {...}

int main(void)
{
  int (*f[2])() = {foo, bar};
  ...
}

如果你想要一个返回f 的函数,那就有点棘手了。 C 函数不能返回数组类型;它们只能返回指向数组的指针,因此您的函数声明将被构建为

        g            -- g
        g()          -- is a function
       *g()          -- returning a pointer
      (*g())[2]      -- to a 2-element array
     *(*g())[2]      -- of pointers
    (*(*g())[2])()   -- to functions
int (*(*g())[2])()   -- returning int

这样的野兽会被这样使用:

int foo() {...}
int bar() {...}

int (*(*g())[2])()
{
  int (*(*f)[2])() = malloc(sizeof *f);
  (*f)[0] = foo;     // the type of the *expressions* foo and bar
  (*f)[1] = bar;     // is `int (*)()`, or pointer to function
  return f;          // returning int
}

int main(void)
{
  int (*(*p)[2])();
  int x, y;
  ...
  p = g();
  x = (*(*p)[0])();
  y = (*(*p)[1])();
  ...
  free(p);
  ...
}

请注意,您还可以使用替换方法从外向内构建毛茸茸的声明。所以,

int x();                   -- x is a function returning int
int (*p)();                -- replace x with (*p) to get a pointer to a function
                                 returning int
int (*a[2])();             -- replace p with a[2] to get an array of pointers 
                                 to functions returning int
int (*(*q)[2])();          -- replace a with (*q) to get a pointer to an array
                                 of pointers to functions returning int
int (*(*g())[2])();        -- replace q with g() to get a function returning
                                 a pointer to an array of pointers to functions
                                 returning int.

相同的结果,不同的路径。我更喜欢第一种方法,但任何一种都应该有效。

许多人建议使用typedef 使内容更易于阅读:

typedef int ifunc();        // ifunc is a synonym for "function returning int"
typedef ifunc *pifunc;      // pifunc is a synonym for "pointer to function
                            //   returning int
typedef pifunc farr[2];     // farr is a synonym for "2-element array of
                            //   pointer to function returning int
typedef farr *pfarr;        // pfarr is a synonym for "pointer to 2-element
                            //   array of pointer to function returning int

pfarr g() 
{
  pfarr f = malloc(sizeof *f);
  (*f)[0] = foo;
  (*f)[1] = bar;
  return f;
}

int main(void)
{
  pfarr p = g();
  int x, y;
  x = (*(*p)[0])();
  y = (*(*p)[1])();
  ...
}

是的,声明更容易阅读,但p 的声明和(*(*p)[1])() 的表达式之间没有联系。你必须通过所有的typedefs 来理解为什么这个表达式是这样写的,为每个typedef 建立一个心理地图。

是的,int (*(*g())[2])() 之类的声明旨在让您目不暇接,将所有内容隐藏在 typedef 后面会使 IMO 情况变得更糟。

【讨论】:

    【解决方案2】:

    不明白你想做什么,也许这可以帮助

    #include<stdio.h>      // printf
    #include<stdlib.h>     // malloc free
    
    int *x();              // forward declaration because used before definition
    
    int main() {
        int *y=x();        // y is a pointer on int 
        printf ("%d %d\n", y[0], y[1]);
        free(y);           // must call free because dynamic allocation
        return 0;
    }
    
    int *x() {
        int *res;
        res=(int*)malloc(sizeof(int)*2);   // dynamic allocation of an array of two int
        // should check res != NULL
        res[0]=10;
        res[1]=20;
        return res;
    }
    

    【讨论】:

      【解决方案3】:

      以下代码将为您提供一个指向函数的指针数组,并且适用于分配、传递数组的标准过程。

      #include <stdio.h>
      #include <stdlib.h>
      
      typedef int (*XFunc())();
      
      XFunc *x[2]; /* array of XFunc pointers */
      
      int f1()
      {
          printf("1\n");
          return 1;
      }
      
      int f2()
      {
          printf("2\n");
          return 2;
      }
      
      int main()
      {
          x[0] = (XFunc*)f1;
          x[1] = (XFunc*)f2;
      
          x[0]();
          x[1]();    
      
          return 0;
      }
      

      上面的指针x将指向(固定)数组中的第一个元素,这个指针值就是要分配给另一个变量的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-29
        • 2018-03-07
        • 1970-01-01
        • 1970-01-01
        • 2011-01-20
        • 2011-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多