链接出现“错误:变量的类型不完整”的问题

时间:2019-09-13 21:23:54

标签: c makefile building

我在构建一个非常基础的项目时遇到了问题。编译器似乎认为我没有定义某种类型,即使该类型已明确定义。运行make时,出现以下错误:

gcc -Wall -pedantic -std=c11   -c -o set.o set.c
gcc -Wall -pedantic -std=c11   -c -o driver.o driver.c
driver.c:12:9: error: variable has incomplete type 'set_t' (aka 'struct set')
  set_t hey;
        ^
./set.h:10:16: note: forward declaration of 'struct set'
typedef struct set set_t;
               ^
1 error generated.

这是我的makefile:

# Makefile for groups

PROG = driver
HEADERS = set.h
OBJS = driver.o set.o

CC = gcc
CFLAGS = -Wall -pedantic -std=c11

$(PROG): $(OBJS)
    $(CC) $(CFLAGS) $^ -o $@

driver.o: set.h set.o
set.o: set.h

.PHONY: clean

clean:
    rm -f *.o

driver.c:

#include <stdio.h>
#include "set.h"

int main (int argc, char* argv[])
{
  set_t hey;

  return 0;
}

set.h:

#ifndef __SET_H
#define __SET_H

typedef struct set set_t;

set_t* set_new();

#endif

set.c:

#include "set.h"
#include <stdlib.h>

typedef struct set {
  int size;
  void** items;
} set_t;

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

您可能已经知道,#include标头在很大程度上意味着将整个文件复制粘贴。

让我们看看如果我们复制粘贴driver.cset.h会发生什么:

driver.c:

#include <stdio.h>
#ifndef __SET_H
#define __SET_H

typedef struct set set_t;

set_t* set_new();

#endif

int main (int argc, char* argv[])
{
  set_t hey;

  return 0;
}

现在我们已经解决了这个问题,让我们关注这一行:

typedef struct set set_t;

此别名将struct set的类型命名为set_t,但是由于以前的代码中没有遇到struct set,因此它也用作前向声明。让我们使该声明更加明显:

struct set;
typedef struct set set_t;

前向声明允许我们做什么?获取有关结构的指针。它不允许我们做什么?创建该类型的对象。我们可以看到这正是我们在main中试图做的事情:

set_t hey; //attempting to create a new object, but fails because the compiler doesn't have all the necessary information about the structure
//the compiler only knows that the structure exists

无论何时声明结构,都在头文件中声明整个结构以及所有typedef和函数原型。 .c文件应仅包含这些函数的定义。让我们更正您的代码:

driver.c:

#include <stdio.h>
#include "set.h"

int main (int argc, char* argv[])
{
  set_t hey;

  return 0;
}

set.h:

#ifndef __SET_H
#define __SET_H

typedef struct set {
  int size;
  void** items;
} set_t;

set_t* set_new();

#endif

set.c:

#include "set.h"
#include <stdlib.h>

//place all the definitions of the functions here, like that set_new() function