我在构建一个非常基础的项目时遇到了问题。编译器似乎认为我没有定义某种类型,即使该类型已明确定义。运行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;
任何帮助将不胜感激!
答案 0 :(得分:1)
您可能已经知道,#include标头在很大程度上意味着将整个文件复制粘贴。
让我们看看如果我们复制粘贴driver.c
,set.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