2012-02-25 43 views
0

这个问题似乎是一个经典的问题,但我没有找到答案:如何声明一个不会生成警告的结构?

我有两个C写的结构类型------结构类型A和结构类型B和B使用A而A同时使用B.

在啊:

#include "b.h" 
struct B; 
typedef struct A { 
    void (*func)(struct B* b); 
}A; 

在BH:

#include "a.h" 
typedef struct B { 
    A a; 
}B; 

虽然这会工作,它的结果---使用函数乐趣,当 “功能”,如果我通过一个变量

B* someb; 

不是:

形式声明
struct B* someb; 

编译时会出现警告,说不兼容的指针类型。这是正常的吗?我可以避免这种警告吗?

+0

http:///stackoverflow.com/questions/252780/why-should-we-typedef-a-struct-so-often-in-c – Mat 2012-02-25 09:45:15

+0

你尝试了什么? – 2012-02-25 09:47:45

+0

对不起,但是我想要做什么我要**避免警告**,因为我想用“B someb;”定义变量而不是“struct B someb;”通过所有情况。那可能吗? – realjin 2012-02-25 09:55:43

回答

2

从您的a.h头文件中,只需删除行#include "b.h"。前向声明struct B;是您所需要的。

该更改将修复循环包含依赖关系,并使使用这些标头的任何代码更加理智。

然后,无论您想要使用B结构,只需包含b.h,并且可以使用它或不使用struct关键字。

某些代码来说明:在a.h头文件:

/* a.h */ 
struct B; 

typedef struct A { 
    void (*func)(struct B* b); 
} A; 

b.h头文件:

/* b.h */ 
#include "a.h" 

typedef struct B { 
    A a; 
} B; 

使用这些头文件的文件:

/* some_file.c */ 
#include "b.h" 

void fun() { 
    B someb; 
    someb.a.func(&someb); 
} 

void fun2() { 
    struct B someb; 
    someb.a.func(&someb); 
} 

两个funfun2 a (从编译器的角度来看 - func尚未初始化,因此调用它将在运行时导致问题)。

+0

是的,你是对的!我错过了前面的声明。顺便说一句,你能告诉我怎样才能清楚你编译器的结构视图(即关于结构声明的这些细节)?我可以阅读什么样的材料? – realjin 2012-02-25 11:07:40

+1

@realjin:当你的代码在语法上是正确的时,编译器很高兴。因此,详细了解C语法有很大帮助。虽然C标准是权威资源,但阅读起来有点困难。但是C上的任何优秀资源都会教你很多。 – 2012-02-25 16:46:37

+0

好的,我明白了,谢谢! – realjin 2012-03-04 04:57:28

0

功能func因为你宣布它得到输入一个指向struct B对象,所以在调用函数时,你应该这样做:

B* somePointer; //because of your typedef you can omit struct 
func(somePointer); 

我省略的内存分配,你还应该管理的部分...

由于SO问题Compiler Warning: Initialization incompatible pointer type显示,您应该传递一个指向该函数的指针,以使更改在对象中可见,否则您只传递一个结构B的副本,并且每次更改只会持续功能范围。

我认为这是警告的原因。

+0

正如我在下面的评论中提到的那样,我的程序运行良好,我想要做的是**避免警告**。 – realjin 2012-02-25 09:57:37

+0

@ user816109不兼容的指针类型是一个典型的警告,当你搞乱了与预定义标准不匹配的指针参数时。 我的猜测是,这个警告的原因是因为我指出,你可以自由接受这个建议。 – Matteo 2012-02-25 10:03:07

+0

对不起,我犯了一个错字---应该是“B * someb;”和“struct B * someb;”。我刚刚纠正了它。 – realjin 2012-02-25 11:09:58

2

循环包含依赖从来不是一个好主意。

最简单的方法是让为struct标签typedef在“A.H”向前声明

typedef struct A A; 
typedef struct B B; 
+0

谢谢,你指出了关键的事情---我错过了前瞻性声明。 – realjin 2012-02-25 13:41:26

0

struct whatever { /* ... */ };定义了一个新的类型。
该新类型名称是struct whatever

可以为类型与typedef无论是在定义类型相同的语句定义的另一个名字

typedef struct whatever { /* ... */ } newtypename; 

或在不同的语句

struct whatever { /* ... */ }; 
typedef struct whatever newtypename; 

你甚至可以定义一个struct类型与没有名字,并得到一个新的名字

typedef struct { /* ... */ } newtypenameforstructwithnotag;