C语言 结构的前向声明

pftdvrlh  于 2023-01-20  发布在  其他
关注(0)|答案(3)|浏览(239)
#include <stdio.h>

struct context;

struct funcptrs{
  void (*func0)(context *ctx);
  void (*func1)(void);
};

struct context{
    funcptrs fps;
}; 

void func1 (void) { printf( "1\n" ); }
void func0 (context *ctx) { printf( "0\n" ); }

void getContext(context *con){
    con=?; // please fill this with a dummy example so that I can get this working. Thanks.
}

int main(int argc, char *argv[]){
 funcptrs funcs = { func0, func1 };
   context *c;
   getContext(c);
   c->fps.func0(c);
   getchar();
   return 0;
}

我好像漏掉了什么。怎么解决?

hyrbngr7

hyrbngr71#

struct(没有typedef)在使用时通常需要(或应该)带有关键字struct。

struct A;                      // forward declaration
void function( struct A *a );  // using the 'incomplete' type only as pointer

如果你用typedef来定义你的结构,你可以省略struct关键字。

typedef struct A A;          // forward declaration *and* typedef
void function( A *a );

请注意,重用结构名称是法律的的
尝试在代码中将forward声明更改为以下形式:

typedef struct context context;

添加一个后缀来指示结构名和类型名可能更易读:

typedef struct context_s context_t;
vpfxa7rd

vpfxa7rd2#

试试这个

#include <stdio.h>

struct context;

struct funcptrs{
  void (*func0)(struct context *ctx);
  void (*func1)(void);
};

struct context{
    struct funcptrs fps;
}; 

void func1 (void) { printf( "1\n" ); }
void func0 (struct context *ctx) { printf( "0\n" ); }

void getContext(struct context *con){
    con->fps.func0 = func0;  
    con->fps.func1 = func1;  
}

int main(int argc, char *argv[]){
 struct context c;
   c.fps.func0 = func0;
   c.fps.func1 = func1;
   getContext(&c);
   c.fps.func0(&c);
   getchar();
   return 0;
}
lqfhib0f

lqfhib0f3#

#include <stdio.h>
struct b; // not needed because:
struct a {
    struct b * pb;  //this member definition also forward declares struct b
    int c;
};

typedef struct a a // needed for a but not struct a because:
struct b {
    struct a* pa;     //this member definition also forward declares struct a
    a * pa1;
    void * c;
};

int main() {
    printf("Hello, world!");
    return 0;
}

基本上,你永远不需要单独正向声明struct b,因为当你用它来执行纯声明时,它总是在行本身声明分部类型,所以这是多余的代码。这种类型的正向声明的唯一好处是它可以和typedef一起使用。在C中,你不需要typedef,因为struct和typedef在同一个标识符命名空间中。因此struct b变得很有用,因为它现在声明了b,所以你会在C中看到它。
关键是如果在你使用它声明一个实际上是试验性的定义而不是一个声明(比如struct e f在文件/块范围内,没有extern)之前,这个类型没有完成,或者如果你试图解引用这个指针,如果它是一个指针,那么你会得到一个不完整的类型错误。
所以它更像是允许你使用一个不完整的类型。忘记forward声明,因为这不是一个单独的操作。它是struct g* h行的一部分。你永远不需要使用其他东西实际上需要的forward声明(除非它是一个typedef),因为它自己的行中有一个forward声明部分。
能够使用不完整的类型允许该类型在稍后被使用之前被完成。你通常会看到正向声明的好处,它被解释为当使用指向该类型的指针时,不必包括包含C++中完整定义的头部,只需要执行class bar,然后bar *,或者当然只使用class bar*而不使用class bar行,如果该特定成员从未被使用。
它也不允许将大小不完整的类型用作结构成员(如果大小是未知的,直到一个包括这样的代码),即使结构体从来没有被用来声明/定义一个变量。我认为这是因为结构体是一个类型,当你提供一个类型的完整定义时,你只能做 * 一次 *,它必须是一个完整的大小,并非不完整(具有未知大小的成员),因此该类型将不可用。永远不会引用包含不完整结构的此结构,而您 * 可以 * 引用大小不完整的不完整类型,这与大小不完整的完整类型相反(只要你不用它定义任何东西),你可以引用,但不能遵从,(地址可以存储在)具有不完整类型的指针中,因为它有完整的大小。只要它的不完整类型不会导致不完整的大小,就可以引用内存。extern struct i j at file /块作用域是允许的,因为除非在代码中引用j,否则将永远不需要它,此时类型必须完整。

相关问题