【问题标题】:Simple header file visibility confusion in CC中简单的头文件可见性混淆
【发布时间】:2011-12-17 15:54:20
【问题描述】:

我在 C 语言中有一个关于包含头文件的奇怪问题。

main.c

#include <stdio.h>
#include <stdlib.h>
#include "location.h"

int waste_new_line();

int main()
{
    location *crossroads = malloc(sizeof(*crossroads));
...

location.h

typedef struct Location_Struct location;

location.c

typedef struct Location_Struct {
    int ID;
    char *name;
    char *description;
} location;

int setup_location(location* l, char* name)
{
    ...

现在这不起作用,因为

location *crossroads = malloc(sizeof(*crossroads));

正在抛出错误:取消引用指向不完整类型的指针意味着它可以看到 location.h 的内容,但它似乎不知道 location.c...

我环顾四周,我看到的所有教程都说链接器会将两个文件链接在一起。

编辑:

我已更改代码以在 location.c 中包含一个初始化程序,如下所示:

main.c

...
#include "location.h"

int waste_new_line();

int main()
{

    location *crossroads = initialize_location();
    ....

location.h

typedef struct Location_Struct location;

location* initialize_location();

location.c

...
typedef struct Location_Struct {
    int ID;
    char *name;
    char *description;
} location;

location* initialize_location(location* l)
{
    return malloc(sizeof(location));
}
...

这仍然抛出相同的错误,但只有当我尝试使用以下方式访问十字路口的成员时:

crossroads->description

这将引发对不完整类型的尊重错误。

编辑 2:现在我决定将结构定义放在头文件中...

【问题讨论】:

  • 位置 *crossroads = malloc(sizeof(location));
  • 文件链接在一起,但不是由编译器链接在一起(或者至少不是由编译器的一部分而不是与您的 C 源代码相关的部分)。哪些教程说明了其他内容?
  • @Krister:不,应该首选 OP 的方法。
  • @delnan:对不起,我的意思是链接器

标签: c header


【解决方案1】:

这种行为是意料之中的。当您#include "location.h" 时,编译器只能看到头文件。 location.c 文件稍后会在链接时出现。

你有两个选择:

  1. 添加一个在location.h 中声明并在location.c 中定义的函数,它执行必要的malloc 并返回一个指针。
  2. 将结构的完整定义移至头文件。

【讨论】:

  • 如果我需要使用 location 作为 location.c 中函数的参数,是否可以选择 2 号?我必须再次包含 location.h 才能访问两个 location.c 中的数据结构,这是不好的做法吗?
  • @JoeBentley:在对应的.c 中包含.h 是标准做法。这样,编译器可以检查您的函数声明和定义是否匹配。
【解决方案2】:

main 文件知道一个名为 Location_Struct 的 struct(和一个 typedef)。它不知道它有多大,因此您不能对其应用sizeof。

由于您有效地隐藏了 Location_Struct 的布局和实现,因此提供一个分配它的“构造函数”是有意义的。

编辑

似乎我不得不提到,“构造函数”是指一个普通函数,它可以访问结构的实现,并且可以分配并可能预填充对象。

【讨论】:

  • C 没有构造函数。
  • -1 试图证明和假冒术语 constructor 的使用,这在C 中绝不是标准的、流行的也不常见的。仅仅接受滑动就足够了。跨度>
  • @Als:我觉得你太苛刻了。在纯 C 中使用类似构造函数的函数是一种非常明智的设计模式。
  • 我不确定是要创建一个函数,还是简单地在 location.h 中包含完整的结构定义
  • @OliCharlesworth:constructor like function 将是一个有效的用法,而不是 constructor,这很可能会误导新用户对不存在的事物提出有趣的想法。
【解决方案3】:

需要将Location_Struct的定义放在头文件location.h中。编译器不会“看到”其他源文件(除非它是#include'd,这通常不是一个好主意)。

【讨论】:

  • 但是我也必须在 location.c 中 #include location.h 因为 location.h 中的函数将类型位置作为参数,在 location.c 中 #include location.h 是不好的做法以及main.c?它会解决我的问题,但我对它是否是个好主意持谨慎态度,我不希望它在未来给我带来麻烦......
  • @JoeBentley:这实际上是正确的做法。每个使用结构的源文件都需要完整的定义。
  • 非常感谢!消除了我的所有担忧。
猜你喜欢
  • 2015-01-04
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
  • 2011-10-08
  • 2010-11-29
  • 2013-03-22
  • 2012-05-26
相关资源
最近更新 更多