简体   繁体   English

C中结构的前向声明?

[英]forward declaration of a struct in C?

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

I am missing something here.我在这里遗漏了一些东西。 Please help me fix this.请帮我解决这个问题。 Thanks.谢谢。

A struct (without a typedef) often needs to (or should) be with the keyword struct when used.结构体(没有 typedef)在使用时通常需要(或应该)与关键字 struct 一起使用。

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

If you typedef your struct you can leave out the struct keyword.如果您对结构进行 typedef,则可以省略 struct 关键字。

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

Note that it is legal to reuse the struct name请注意,重用结构名称是合法的

Try changing the forward declaration to this in your code:尝试将代码中的前向声明更改为:

typedef struct context context;

It might be more readable to do add a suffix to indicate struct name and type name:添加一个后缀来指示结构名称和类型名称可能更具可读性:

typedef struct context_s context_t;

Try this尝试这个

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

Basically, you never need to forward declare struct b on its own, because it always declares the partial type on the line itself when you use it to perform a pure declaration, so this is redundant code.基本上,您永远不需要自己转发声明struct b ,因为当您使用它执行纯声明时,它总是在行本身上声明部分类型,因此这是多余的代码。 The only benefit of this type of forward declaration is it can be used with a typedef.这种类型的前向声明的唯一好处是它可以与 typedef 一起使用。 In C++, you don't need the typedef because struct and typedefs are in the same identifier namespace, so therefore struct b becomes useful because it now declares b , so you will see it in C++.在 C++ 中,您不需要 typedef,因为 struct 和 typedefs 在同一个标​​识符命名空间中,因此struct b变得有用,因为它现在声明了b ,因此您将在 C++ 中看到它。

The whole point is if that type isn't completed before you use it to declare something that is actually a tentative definition and not a declaration (so struct ef at file / block scope without extern ) that isn't a pointer, or if you attempt to dereference the pointer if it is a pointer, then you will get an incomplete type error.重点是如果该类型在您使用它来声明实际上是暂定定义而不是不是指针的声明(因此在文件/块范围内没有extern struct ef )之前没有完成,或者如果您如果它是一个指针,则尝试取消引用该指针,那么您将得到一个不完整的类型错误。

So it's more like it allows you to use an incomplete type.所以它更像是允许您使用不完整的类型。 Forget about forward declaration because this isn't a separate action.忘记前向声明,因为这不是一个单独的动作。 It's part of the line struct g* h .它是struct g* h行的一部分。 You never need to use a forward declaration that something else actually requires (unless it's a typedef), because it has a forward declaration part of its own line.您永远不需要使用其他东西实际需要的前向声明(除非它是 typedef),因为它有自己行的前向声明部分。

Being able to use an incomplete type allows the type to be completed later on, before it is used.能够使用不完整的类型允许稍后在使用之前完成该类型。 You typically see the benefits of forward declaration explained as not having to include the header containing the full definition in C++ when using a pointer to the type, only needing to do class bar and then bar * , or of course just using class bar* without class bar line, if this particular member is never used.您通常会看到前向声明的好处被解释为在使用指向类型的指针时不必在 C++ 中包含包含完整定义的标头,只需要执行class bar然后bar * ,或者当然只使用class bar*而没有class bar线,如果从未使用过此特定成员。

It doesn't let you use a type with incomplete size as a struct member either (if the size is unknown up to an including this like of code), even if the struct is never used to declare / define a variable.它也不允许您使用大小不完整的类型作为结构成员(如果大小未知,直到包含此类代码),即使该结构从未用于声明/定义变量。 I think this is because the struct is a type, and when you provide the complete definition of a type, which you can only do once , it has to be of a complete size, not incomplete (having a member of unknown size), so the type would be unusable.我认为这是因为结构是一种类型,当你提供一个类型的完整定义时,你只能做一次,它必须是完整的大小,而不是不完整的(具有未知大小的成员),所以该类型将无法使用。 This struct containing the incomplete struct never be referenced, whereas you can reference an incomplete type with incomplete size as opposed to a complete type with incomplete size (as long as you don't define anything with it), and you can reference, but not deference, (an address can be stored in) a pointer with incomplete type, because it has complete size.含从来没有完整的结构这个结构被引用,而你可以用,而不是一个完整的类型与尺码不全(只要你不定义与它的任何东西)尺码不全引用一个不完整的类型,你可以参考,但不尊重,(一个地址可以存储在)一个不完整类型的指针,因为它有完整的大小。 You can reference memory so long as its incomplete type doesn't entail an incomplete size.您可以引用内存,只要其不完整的类型不包含不完整的大小。 extern struct ij at file / block scope is allowed because it will never be needed unless j is referenced in the code, by which time the type must be complete.允许在文件/块范围内使用extern struct ij ,因为除非在代码中引用j ,否则永远不需要它,此时类型必须完整。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM