C抽象数据类型指针 - 程序模块化

时间:2015-04-10 02:30:20

标签: c struct abstract-data-type

如果某个模块依赖于某个其他子模块,要么将其包含在其标题中,要么包含在其代码文件中,以及除了对主程序有贡献之外,模块是否也相互依赖?

下图示意性地说明了module1.h / .c需要子模块module4.h,而module2需要module3的情况。

Example

每个头文件都有自己的typedef结构例:

typedef struct list * List;

和与头文件相关的源文件实现结构如:

struct list {
    unsigned length;
    char * value;
};

我在头文件中有另一个结构:

typedef enum {START, END, MIDDLE, COMMENTS, CONDITIONS} TypeListBal;
typedef struct bal * Bal;

和源文件:

struct bal {
    TypeListBal type;
    List name;              // Name of the bal
    List attributes[];          // Array of type struct List
};

我今晚读了很多,而且我对一件事情不太确定。如果我只是在我的案例中包含我需要的源文件中的头文件,我在bal.c中包含list.h,因为我的bal.c得到了一个结构定义,作为List类型的成员

为了使它工作,我是否必须在我的所有模块中放置特定的#INCLUDE,或者在编译时完成工作?

我的意思是在make makefile中,拥有我的bal.o对象,它看起来像:

bal.o: list.o bal.c bal.h
       $(CC)   -g -W -Wall -c  list.o bal.c bal.h

因此,只要makefile尝试编译bal.o,编译器就会看到所有依赖项,并且能够编译所有内容。

这就是我的理解方式但是当我尝试这个时,我得到了:

error: dereferencing pointer to incomplete type

我猜它是因为在我的bal.c文件中,我声明了struct List类型的变量,并且编译器没有关于struct List的任何想法导致定义struct list的列表在list.c文件中。

所以问题又是: 如何连接所有内容以使其正常工作?

2 个答案:

答案 0 :(得分:1)

您的标头文件已损坏。这是一个不完整的类型:

typedef struct bal * Bal;

它需要struct声明才能完成。那也应该在头文件中。如果在C代码中你说*Bal没有完整的类型,编译器就会放弃,因为它没有关于这个表达式的含义的任何信息,即结构的字段。

您正在显示的依赖关系图应该完全没问题。您希望使用防护来确保头文件仅包含一次。然后你可以包含一个来自另一个的头,而​​C预处理器将会#34;正好工作"只要没有循环依赖。在您的情况下,标题为例如模块4看起来像:

// module4.h
#ifndef MODULE_4_H_INCLUDED
#define MODULE_4_H_INCLUDED

#include "module1.h"

// all public type declarations for module 4 types

#endif // MODULE_4_H_INCLUDED

使用自己的守护定义使所有标题(包括module1.h)相似。然后模块4代码:

// module4.c
#include "module4.h"

// Use module 4 types.

通常,如果您需要某个.c文件中的头文件给出的类型,即使它被头文件之间的依赖项包含在内,也要包括它。警卫通常会确保没有裁员。

此外,您对make依赖关系的想法是错误的。例如。要成功汇编module4.c以获取module4.o,您需要(当然)module4.cmodule4.hmodule1.h。这些是构建依赖项。因此规则将是:

module4.o : module4.c module4.h module1.h
        $(CC) -g -W -Wall -c module4.c

但你不应该写这样的具体规则。 Make具有易于使用的内置函数和一般规则。您可以使用gcc本身生成头文件依赖项,而不是手动跟踪它们(这可能会导致各种灾难)。请参阅the -M option

答案 1 :(得分:0)

如果编译器只看到:

typedef struct list * List;

在包含的文件中,当编译器编译特定的* .c文件时,在其他地方没有struct list的定义,如果* .c文件中的代码将List指针取消引用访问List结构的成员,将报告错误,因为尚未定义struct list

仅仅因为struct list的定义存在于某个其他文件中,在同一目录中的其他位置,单独编译,并不意味着编译器在编译时会知道它是什么这个文件。

单个* .c文件的编译是与编译任何其他* .c文件完全不同的过程,编译器只会看到明确{{1}的结构,函数和其他内容的定义。在编译那个特定文件时,直接在#include文件中声明。