请注意:这不是作业。该程序不完整,并没有完全发挥作用,但至少应该编译。
我正处于使用C Primer Plus Book的自学过程中(简而言之,我是C的新手)。我几乎已经完成了对整本书的阅读,并且已经完成了每一章的练习,并且我不时地完成了切线。这是其中一次。我遇到了一个特殊的问题,我很确定这与预处理程序指令有关。
我正在使用MinGW(gcc for windows)并报告:
gcc报告的错误是:
nanfunct.c:'关键字的多重定义'
nanite.c:首先在此定义
等......等......更多错误......
我很确定这是由于包含多个头文件引起的,但更重要的是我创建然后包含的头文件导致了这个问题。
这个问题似乎与指向char-arrays(或基于字符串的数组)有关,这些数组在编译时是重复的,即使我说只有在尚未预定义的情况下才定义它。
例如:
#ifndef MENU_OPTIONS
# define MENU_OPTIONS ON
# if MENU_OPTIONS == ON
...some code here...
char * keywords[] = {
"copy", "help", "line",
"quit", "read", "write"
};
char * keyletters[] = {
"c", "h", "l",
"q", "r", "w"
};
# endif
#endif
我使用的是三个文件:
nanite.c - > main()的源文件
nanfunct.c - >功能的源文件
nanproto.h - > nanite.c和nanfunct.c的头文件
nanite.c 和 nanfunct.c 内部 #include nanproto.h
在pastebin上发布的源文件:
nanproto.h - > nanite.c 和 nanfunct.c 的头文件 nanite.c& nanfunct.c - >源文件
为什么会这样?我认为 #ifndef 应该让这样的事情发生吗?
答案 0 :(得分:4)
您误解了预处理器的功能,或者C源文件的编译和链接方式。
每个源文件都是单独预处理的。因此,在预处理之后,nanfunct.c包含keywords
和keyletters
的定义。然后将预处理的源编译到目标文件nanfunct.o。
预处理后,nanite.c还包含keywords
和keyletters
的定义。编译此预处理源以生成目标文件nanite.o。
然后链接器尝试将nanfunct.o和nanite.o结合起来。它发现keywords
和keyletters
有多个定义,因此它会显示错误消息并中止。
如果您希望在多个源文件中提供某些内容,通常的模式是将声明放在头文件中,并将定义放在一个源文件中。
移动它:
char * keywords[] = {
"copy", "help", "line",
"quit", "read", "write"
};
char * keyletters[] = {
"c", "h", "l",
"q", "r", "w"
};
进入nanite.c 或 nanfunct.c(不是两者)。将这些声明添加到nanite.h:
extern char * keywords[];
extern char * keyletters[];
这样,定义只包含在一个目标文件中。
请注意,这仅适用于全局变量和函数。它不适用于结构,联合,枚举或typedef,因为它们不包含在目标文件中。
答案 1 :(得分:2)
您通过在.h文件中添加定义来犯错误。只有声明进入.h文件。
如果你把它(一个定义):
char * keywords[] = { "foo" };
<。>在.h文件中,然后将其包含在多个C文件中,您使用的#ifdef
类型无关紧要,您仍将最终定义定义的变量在项目的多个位置。
要记住的关键是每个.c文件都是独立于其他文件编译的。这意味着,如果您#define
在另一个C文件中发送某些内容并不重要。
你的.h文件应该是这样的:
extern char *keywords[];
然后一个 .c文件应提供定义。