如何处理接口和实现中类型和转发声明的不完整定义

时间:2014-10-02 16:02:11

标签: c struct forward-declaration incomplete-type

好的,我来这个问题。这个问题已被提出,但没有专门针对未对.h文件进行更改的情况做出回答,因此请不要通过说"哦,将其移至.h文件& #34 ;.我目前正在上课,老师递给我们.h文件说,对此做一个实现,不要改变.h文件中的任何内容。我按照建议将结构等移动到我之前项目中的.h文件中,并因此而在我的成绩上受到很大影响

所以,话虽如此,让我发布一些代码并深入了解细节。

.h文件

#ifndef _list_h
#define _list_h

typedef char *ListItemP  //a pointer to an item in the list
typedef struct List *ListP //a pointer to the List struct itself

somefunctions();

#endif

.c文件

#include "List.h"
struct List
{
    int foo;
    ListItemP bar;
};

ListP newList()
{
    // implementation, I understand and am confident I used malloc 
    // and everything else correctly to make a new struct
}

main.c或tester.c或者您想要调用它的文件,我测试实现和接口(分别是.c和.h)

#include <stdio.h>
#include <stlib.h>
#include "List.h"

int main()
{
     ListP n1 = newList();
     n1->foo = 5;

     return 0;
}

这些是我在使用gcc -O List.c main.c在我的unix(osx)终端上编译后得到的错误

 main.c:16:5: error: incomplete definition of type 'struct List'

 n1->foo = 5;
 ~~^

./List.h:21:16: note: forward declaration of 'struct List'

 typedef struct List *ListP;
           ^
 1 error generated.

任何帮助将不胜感激,如果您坚持将我与之前提出的问题联系起来,请指出该问题的哪个部分他们回答了我问题的具体部分。也许我错过了,但我觉得好像我已经彻底检查了这些问题。从本课程开始以来,这个问题一直困扰着我,所以一段代码可以让我直截了当,但是我喜欢一个解释,所以我终于明白我做错了什么。谢谢谢谢谢谢。

2 个答案:

答案 0 :(得分:1)

由于List的定义仅由&#34; .c&#34;文件然后访问其成员的所有代码必须在那里。这是一种有效的技术,您可以强制所有其他源文件仅处理指针而不处理其成员。因此,您的测试人员代码应该调用在&#34; .c&#34;中实现的功能。文件以填充它。

void
setFoo(ListP p, int foo);

int main()
{
     ListP n1 = newList();
     setFoo(n1, 5);

     return 0;
}

在&#34; .c&#34;文件在哪里&#39;列出&#39;定义如下:

void
setFoo(ListP p, int foo)
{
    p->foo = foo;
}

无论如何,&#39; setFoo&#39;的原型需要对您的测试人员程序可见。您可能希望在头文件中定义它,或者只是将其添加到测试器主体本身。

答案 1 :(得分:0)

要访问结构中的成员字段,代码需要知道存在哪些成员字段。如果代码没有结构定义,它将不知道结构中的成员字段,编译将失败。这就是结构通常在头文件中定义的原因。

因此,解决问题的简单方法是将结构List放在list.h头文件中。如果您无法修改头文件,则需要创建另一个包含结构定义的头文件,并在list.h头文件之前包含该头文件。如果你不能这样做,那么你需要让你的程序成为一个单一的源文件。如果你甚至不能这样做那么你的问题是无法解决的。