【问题标题】:C - struct definition in header filesC - 头文件中的结构定义
【发布时间】:2015-04-09 02:32:57
【问题描述】:

我有这两个结构,它们的头文件附带。

我的结构编号 1 是:

头文件“list.h”:

typedef struct list * List;

源文件“list.c”:

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

我的结构号 2 是:

头文件“bal.h”:

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

源文件“bal.c”:

i've include those header files : 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "list.h"

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

当我尝试在我的 bal.c 文件中使用一个函数时:

Bal createBal(List name){

char * search;
const char toFind = '=';
    search = strchr(name->value, toFind);

}

我在这一行遇到错误:search = strchr(name-&gt;value, toFind); 说:错误:取消引用指向不完整类型的指针

我不知道为什么,因为我已经在我的 bal.c 中包含了 list.h

我读过很多关于 Stackoverflow 的文章,说它被称为这种类型的编程:不透明类型 这似乎真的很好,但我不知道如何将我的其他头文件使用到其他源文件中。 我认为我所要做的就是将我的 list.h 包含在我的 bal.c 文件中。

我在 gcc 中使用这个命令进行编译:gcc -g -W -Wall -c bal.c bal.h

非常感谢!

【问题讨论】:

  • 头文件只是在许多其他源文件中包含通用预定义代码的一种便捷方式...一个问题——如果它不在头文件中,它不会被包含在任何源文件中源文件。您的结构定义不在头文件中...
  • 不要在编译命令中包含 .h 文件。
  • 你至少应该看看Am I correct to assume one cannot forward declare a library's opaque pointer type? 关于同一主题还有其他问题。基本的一点是,如果你有一个不透明的类型,例如list.h 中的List,你不能在指定了确切结构定义的文件之外访问该类型的成员(这意味着只有list.c 可以访问@ 987654332@ 或 length List 的成员)。
  • 建议:1) 不要 typedef 结构定义。 2)将结构定义放在头文件中。 3) bal.c 需要包含 bal.h 头文件。 4) 将结构声明(实际的结构对象)放在使用它们的文件中。

标签: c gcc compiler-errors opaque-pointers


【解决方案1】:

.h 文件只有struct 和typedef 的声明。

typedef struct list * List;

这并没有提供任何关于struct 成员是什么的线索。它们被“隐藏”在 .c 文件中。编译器在编译bal.c时,无法知道struct list有一个成员value。

您可以通过以下几种方式解决此问题:

  1. 将struct list的定义也放在.h文件中。
  2. 提供可以获取/设置struct list 对象值的函数。

【讨论】:

  • 您的选项 2 说我必须提供结构列表的一些 getter/setter 函数。我是否包括在我的 list.c 或 bal.c 中起作用?因为我们不能改变或添加任何东西到头文件,这就是为什么我有点困惑,不知道如何处理它。
  • getter 和 setter 必须在 .h 文件中提供,否则你又回到了原点:编译器看不到定义。
【解决方案2】:

当您包含头文件时,这就是您所做的一切。在您的头文件中,您只有以下行:

typedef struct list * List;

尝试从 main 使用这个结构会导致编译器抱怨类型不完整,因为从源文件的角度来看,这个结构没有成员。事实上它根本没有定义。

你需要输入:

struct list;
typedef struct list * List;

在您的头文件中。但是,请注意,此过程会创建一个不透明的结构!这意味着做例如

List l1;
l1->data = 0; //error

不允许,因为编译器只能看到头文件中包含的内容。在该编译单元中,结构中不存在变量。

这个可以被有意使用,强制用户为你的数据类型通过getter/setter。类似的东西

int data = ListStuff_Get_Item1(l1);

可以,但是ListStuff_Get_Item1()函数需要在.h中声明,在.c中定义。

【讨论】:

  • 我明白你的回答,但是如果我无法在我的头文件中添加或更改任何内容怎么办?正如你所说,我的函数 Bal createBal(List name) 已经在我的 .h 文件(bal.h) 中声明,并且我在我的 .c (bal.c) 中定义了它但是我的函数的第一个参数是一个结构列表,并且作为我明白了,即使我确实在我的 bal.c 中包含了 list.h,编译器也不知道或不知道 List 是否有成员!
  • 仔细检查作业,询问老师是否正确。除此之外,您需要在 typedef 之前声明和定义结构。如果您绝对不能修改.h,那么只需在.c 文件中需要的地方声明它,并在定义后#include .h 文件。
  • 建议添加一个包含所有结构定义的头文件,并从 .c 文件中删除这些结构定义
  • 哇!将所有结构定义包含在单个头文件中并将此头文件包含在我的所有源文件中解决我的问题。非常感谢!!
猜你喜欢
  • 2013-10-15
  • 1970-01-01
  • 2018-04-16
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多