这不适用于foo
struct Foo;
typedef struct
{
int x;
}
Bar;
void foo (Foo *); // unknown type name ‘Foo’
void bar (Bar *);
typedef struct
{
int y;
}
Foo;
这不适用于bar
struct Foo;
typedef struct
{
int x;
}
Bar;
void foo (struct Foo *);
void bar (struct Bar *); ‘struct Bar’ declared inside parameter list
typedef struct
{
int y;
}
Foo;
我的一些结构必须是前向声明的,因为它们作为指针传递,其中一些必须不是前向声明的,因为它们是作为值传递的。
有没有办法在C中声明类型,这样所有函数原型都可以始终以相同的方式始终引用自定义类型,无论它们是否是前向声明的?
答案 0 :(得分:1)
struct Foo;
声明名为Foo
的结构。但是,您必须声明名为Foo
的结构的typedef Foo
。
#include <stdio.h>
typedef struct Foo Foo;
typedef struct {
int x;
} Bar;
void foo(Foo *);
void bar(Bar *);
struct Foo {
int y;
};
int main(void) {
printf("Hello, world!\n");
}
答案 1 :(得分:1)
第一项业务是指出在您的示例中没有struct Foo
。只有一个没有标记的结构,typedef
为Foo
。 1
有没有办法在C中声明类型,这样所有函数原型都可以始终以相同的方式始终引用自定义类型,无论它们是否是前向声明的?
struct
的定义或声明应该出现在函数参数列表中使用结构之前。否则,声明范围只是函数原型,几乎可以肯定不是你想要的。
实现目标的方法只有通过严格的编码才能实现。
前向声明是您真正需要的功能原型。在定义或调用函数本身之前,您不需要完整的结构定义。
struct Foo;
void foo (struct Foo); // Okay, only at the call site or definition site
// do we need the full struct definition.
简短example来演示
#include <stdio.h>
struct Foo;
void foo (struct Foo);
struct Foo
{
int y;
};
int main(void) {
struct Foo f = { .y = 1 };
foo(f);
return 0;
}
void foo (struct Foo f)
{
printf("%d", f.y);
}
当定义和声明在不同的翻译单位之间展开时,可以更清楚,但上述情况必须这样做。
所以我建议你,在将它们用于函数原型(通过指针或值)之前,你总是在单独的行上声明你的结构。并且在真正需要之前不要引入完整的定义。
1 fa.linux.kernel上的一个可爱的信件,其中Linus Torvalds比我更清楚地说明为什么你更喜欢使用完整的struct标签。
答案 2 :(得分:1)
您的问题不是前向宣布与非前瞻宣称,而是struct X
与typedef struct { ... } X
。
您可以仅使用struct X
解决此问题:
struct Foo;
struct Bar
{
int x;
};
void foo (struct Foo *);
void bar (struct Bar *);
struct Foo
{
int y;
};
完成后,您可以引入typedef
名称:
typedef struct Foo Foo;
typedef struct
{
int x;
}
Bar;
void foo (Foo *);
void bar (Bar *);
struct Foo
{
int y;
};
您无法预先声明typedef
,因此我们仍需要我们可以转发的真实struct
类型。这里有一个小的不一致:Foo
与struct Foo
相同,但没有struct Bar
,只有Bar
。你可以通过切换到
typedef struct Bar
{
int x;
}
Bar;
同时定义struct Bar
和Bar
。
答案 3 :(得分:-1)
C支持的唯一“前向声明”和引用是指针,例如:
void myFunc (struct XYZ *p);
这告诉编译器你指的是一个类型struct XYZ
,可能还没有声明,你要传递一个指针。这允许编译器在不知道该结构实际包含的内容的情况下执行类型检查。
请注意,指针大小都相同,因此不会检查指针本身,只检查它指向的东西。
另请参阅使用typedef
解释的其他解决方案。
答案 4 :(得分:-2)
混合前向声明和类型定义。两者都是不同的东西。如果你想使用前向声明的结构的相同类型的用法:
struct Foo; // forward declaration
struct Bar { int x; }; // definition
void foo(struct Foo); // works for a prototype
void bar(struct Bar); // works for a prototype
您无法转发声明类型定义。也许这就是名称定义的原因。但是,您可以键入define forward forward:
struct Foo; // forward declaration
typedef struct Foo Foo_t; // type definition of a forward declaration
struct Bar { int x; }; // definition
typedef struct Bar Bar_t; // type definition of a definition
void foo(Foo_t); // works
void bar(Bar_t); // works
如果您有一个功能定义,则必须完成该类型。这意味着您已经在此位置定义了前向声明的类型,或者您必须使用指针。再说一遍:无论你使用结构还是类型定义都没关系。
顺便说一句:正如你在我的例子中所看到的那样,城市传说中不完整的结构类型必须通过“引用”传递。您可以在函数声明(原型)中使用不完整类型。但是,当您定义函数时,必须完成类型。在大多数情况下,这都不成交。