[英]What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?
I am a beginner in C programming and I know the difference between struct
type declaration and typedef
struct declaration. 我是C编程的初学者,我知道
struct
类型声明和typedef
结构声明之间的区别。 I came across to know an answer saying that if we define a struct
like: 我碰到一个答案,说如果我们定义一个
struct
如:
typedef struct {
some members;
} struct_name;
Then it will be like providing an alias to an anonymous struct (as it is not having a tag name). 然后就像为匿名结构提供别名(因为它没有标签名称)。 So it can't be used for forward declaration.
因此,它不能用于前向声明。 I don't know what the forward declaration means.
我不知道向前声明的意思。
Also, I wanted to know that for the following code: 另外,我想知道以下代码:
typedef struct NAME {
some members;
} struct_alias;
Is there any difference between NAME
and struct_alias
? NAME
和struct_alias
有什么区别? Or are both equal as struct_alias
is an alias of struct NAME ? 还是两者都相等,因为
struct_alias
是struct NAME的别名?
Furthermore, can we declare a variable of type struct NAME
like these: 此外,我们可以这样声明一个类型为
struct NAME
的变量struct NAME
:
struct_alias variable1;
and/or like: 和/或类似:
struct NAME variable2;
or like: 或类似:
NAME variable3;
struct
forward declarations can be useful when you need to have looping struct declarations. 当需要循环结构声明时,
struct
前向声明会很有用。 Example: 例:
struct a {
struct b * b_pointer;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
When struct a
is declared it doesn't know the specs of struct b
yet, but you can forward reference it. 声明
struct a
时,尚不知道struct b
的规格,但您可以转发引用它。
When you typedef an anonymous struct then the compiler won't allow you to use it's name before the typedef. 当您对匿名结构进行类型定义时,编译器将不允许您在类型定义之前使用其名称。
This is illegal: 这是非法的:
struct a {
b * b_pointer;
int c;
};
typedef struct {
struct a * a_pointer;
void * d;
} b;
// struct b was never declared or defined
This though is legal: 这是合法的:
struct a {
struct b * b_pointer;
int c;
};
typedef struct b {
struct a * a_pointer;
void * d;
} b;
// struct b is defined and has an alias type called b
So is this: 这是这样的:
typedef struct b b;
// the type b referes to a yet undefined type struct b
struct a {
b * struct_b_pointer;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
And this (only in C, illegal in C++): 这(仅在C中,在C ++中是非法的):
typedef int b;
struct a {
struct b * struct_b_pointer;
b b_integer_type;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
// struct b and b are two different types all together. Note: this is not allowed in C++
Forward declaration is a promise to define something that you make to a compiler at the point where the definition cannot be made. 前向声明是一种承诺,可以在无法进行定义的时候定义您对编译器所做的事情。 The compiler can use your word to interpret other declarations that it would not be able to interpret otherwise.
编译器可以使用您的单词来解释其他无法解释的声明。
A common example is a struct
designed to be a node in a linked list: you need to put a pointer to a node into the struct
, but the compiler would not let you do it without either a forward declaration or a tag: 一个常见的示例是一个
struct
,该struct
设计为链接列表中的一个节点:您需要在该struct
放置一个指向节点的指针,但是如果没有前向声明或标记,编译器将不允许您这样做:
// Forward declaration
struct element;
typedef struct {
int value;
// Use of the forward declaration
struct element *next;
} element; // Complete definition
and so it cant be used for forward declaration
所以它不能用于前向声明
I think that author's point was that giving your struct
a tag would be equivalent to a forward declaration: 我认为作者的观点是给您的
struct
一个标签将等同于一个前向声明:
typedef struct element {
int value;
// No need for a forward declaration here
struct element *next;
} element;
Forward declaration is a declaration preceeding an actual definition, usually for the purpose of being able to reference the declared type when the definition is not available. 前向声明是在实际定义之前的声明,通常是为了在该定义不可用时能够引用已声明的类型。 Of course, not everything may be done with the declared-not-defined structure, but in certain context it is possible to use it.
当然,不是所有的事情都可以使用声明的未定义结构来完成,但是在某些情况下可以使用它。 Such type is called incomplete , and there are a number of restrictions on its usage.
这种类型称为不完整类型,其使用受到许多限制。 For example:
例如:
struct X; // forward declaration
void f(struct X*) { } // usage of the declared, undefined structure
// void f(struct X) { } // ILLEGAL
// struct X x; // ILLEGAL
// int n =sizeof(struct X); // ILLEGAL
// later, or somewhere else altogether
struct X { /* ... */ };
This can be useful eg to break circular dependencies, or cut down the compilation time, as the definitions are usually significantly larger, and so more resources are required to parse it. 这可能很有用,例如打破循环依赖关系或减少编译时间,因为定义通常要大得多,因此需要更多资源来解析它。
In your example, struct NAME
and struct_alias
are indeed equivalent. 在您的示例中,
struct NAME
和struct_alias
实际上是等效的。
struct_alias variable1;
struct NAME variable2;
are correct; 是正确的;
NAME variable3;
is not, as in C the struct
keyword is required. 不是,因为在C中,
struct
关键字是必需的。
struct_alias
and struct NAME
are same , struct_alias
is an alias to struct NAME
struct_alias
和struct NAME
相同, struct_alias
是struct NAME
的别名
These both are same and allowed 这两者是相同的,并且允许
struct_alias variable1;
struct NAME variable1;
this is illegal 这是非法的
NAME variable3;
See this article on Forward declaration 请参阅有关前向声明的文章
As others stated before, a forward declaration in C/C++ is the declaration of something with the actual definition unavailable. 如前所述,C / C ++中的前向声明是对实际定义不可用的内容的声明。 Its a declaration telling the compiler "there is a data type ABC".
它的声明告诉编译器“存在数据类型ABC”。
Lets pretend this is a header for some key/value store my_dict.h
: 让我们假装这是一些键/值存储
my_dict.h
的标头:
...
struct my_dict_t;
struct my_dict_t* create();
char* get_value(const struct my_dict_t* dict, const char* name);
char* insert(struct my_dict_t* dict, const char* name, char* value);
void destroy(struct my_dict_t* dict);
...
You dont know anything about my_dict_t
, but actually, for using the store you dont need to know: 您对
my_dict_t
,但是实际上,使用商店不需要知道:
#include "my_dict.h"
...
struct my_dict_t* dict = create();
if(0 != insert(dict, "AnEntry", strdup("AValue"))) {
...
}
...
The reason for this is: You are only using POINTERS to the data structure. 原因是:您仅对数据结构使用POINTERS。
POINTERS are just numbers, and for dealing with them you dont need to know what they are pointing at. 指针只是数字,与它们打交道时,您无需知道它们的指向。
This will only matter if you try to actually access them, like 这仅在您尝试实际访问它们时才有意义,例如
struct my_dict_t* dict = create();
printf("%s\n", dict->value); /* Impossible if only a forward decl is available */
So, for implementing the functions, you require an actual definition of my_struct_t
. 因此,为了实现这些功能,您需要一个实际的
my_struct_t
定义。 You might do this in the source file my_dict.c
like so: 您可以这样在源文件
my_dict.c
执行此操作:
#include "my_dict.h"
struct my_dict_t {
char* value;
const char* name;
struct my_dict_t* next;
}
struct my_dict_t* create() {
return calloc(1, sizeof(struct my_dict_t));
}
This is handy for several situations, like 这在几种情况下都很方便,例如
So the question that remains is: Why cant we just omit the forward declaration at all when using the functions above? 所以剩下的问题是:为什么在使用上述函数时我们根本不能完全省略前向声明? In the end, it would suffice for the compiler to know that all
dict
are pointers. 最后,编译器知道所有
dict
都是指针就足够了。
However, the compiler does perform type checks: It needs to verify that you don't do something like 但是,编译器会执行类型检查:它需要验证您没有执行类似的操作
...
int i = 12;
char* value = get_value(&i, "MyName");
...
It does not need to know how my_dict_t
looks like, but it needs to know that &i
is not the type of pointer get_value()
expects. 它不需要知道
my_dict_t
样子,但是需要知道&i
不是get_value()
指针的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.