在C中转发结构的声明?

时间:2012-04-03 18:50:58

标签: c struct declaration forward

#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;
}

我在这里遗漏了一些东西。请帮我解决这个问题。感谢。

3 个答案:

答案 0 :(得分:32)

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

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

如果你输入你的结构,你可以省略struct关键字。

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

请注意,重用结构名称

是合法的

尝试在代码中将前向声明更改为:

typedef struct context context;

添加后缀以指示结构名称和类型名称可能更具可读性:

typedef struct context_s context_t;

答案 1 :(得分:31)

试试这个

#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;
}

答案 2 :(得分:0)

#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 和 typedefs 在同一个标​​识符命名空间中,因此 struct b 变得有用,因为它现在声明了 b,所以您将在 C++ 中看到它。

重点是如果该类型在您使用它来声明实际上是暂定定义而不是声明的内容之前没有完成(因此 struct e f 在文件/块范围内没有 extern)这不是一个指针,或者如果您尝试取消引用该指针(如果它是一个指针),那么您将得到一个不完整的类型错误。

所以它更像是允许您使用不完整的类型。忘记前向声明,因为这不是一个单独的动作。它是行 struct g* h 的一部分。您永远不需要使用其他东西实际需要的前向声明(除非它是 typedef),因为它有自己行的前向声明部分。

能够使用不完整的类型允许稍后在使用之前完成该类型。您通常会看到前向声明的好处被解释为在使用指向类型的指针时不必在 C++ 中包含包含完整定义的标头,只需执行 class bar 然后执行 bar *,或者当然如果从未使用过此特定成员,则仅使用 class bar* 而不使用 class bar 行。

它也不允许您使用大小不完整的类型作为结构成员(如果大小未知直到包含此类代码),即使该结构从未用于声明/定义变量。我认为这是因为结构是一种类型,当你提供一个类型的完整定义时,你只能做一次,它必须是完整的大小,而不是不完整的(有一个未知大小的成员),因此该类型将无法使用。这个包含不完整结构的结构永远不会被引用,而你可以引用一个大小不完整的不完整类型,而不是一个大小不完整的完整类型(只要你没有用它定义任何东西),并且您可以引用但不能引用(地址可以存储在)类型不完整的指针,因为它具有完整的大小。您可以引用内存,只要其不完整的类型不包含不完整的大小。文件/块范围内的 extern struct i j 是允许的,因为除非在代码中引用 j,否则永远不需要它,此时类型必须完整。