我是否以错误的方式使用预处理器?
Am I Utilizing the Preprocessor the Wrong Way?
请注意:这不是家庭作业。该程序不完整且功能不全,但至少应该可以编译。
我正在使用 C Primer Plus Book 自学(简而言之,我是 C 的新手)。我几乎读完了整本书,并且一直在完成每一章的练习,有时我会跑题。这是那些时代之一。我 运行 遇到了一个特殊问题,我很确定它与预处理器指令有关。
我正在使用 MinGW(windows 的 gcc)并且它报告:
The error that gcc reports is:
nanfunct.c: multiple definition of 'keywords'
nanite.c: first defined here
etc... etc... more errors...
我很确定这是由于包含多个头文件引起的,但更重要的是我创建然后包含的头文件导致了这个问题。
这个问题似乎与指向字符数组(或基于字符串的数组)的指针有关,它们在编译时被复制,尽管我说只有在尚未预定义的情况下才定义它。
例如:
#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
I am using three files:
nanite.c -> source file for main()
nanfunct.c -> source file for functions
nanproto.h -> header file for nanite.c and nanfunct.c
nanite.c 和 nanfunct.c 内部 #include nanproto.h
source files posted on pastebin:
nanproto.h -> Header File for nanite.c and nanfunct.c
nanite.c & nanfunct.c -> source files
为什么会这样?我以为 #ifndef 应该可以防止这样的事情发生?
您将 definitions 放入 .h 文件中是错误的。只有 声明 进入 .h 文件。
如果你把这个(定义):
char * keywords[] = { "foo" };
在一个.h文件中,然后将其包含在多个C文件中,无论您使用哪种#ifdef
ery,您最终都会得到该变量在项目的多个地方定义。
要记住的关键是每个 .c 文件都是独立于其他文件编译的。这意味着,您是否在另一个 C 文件中 #define
d 并不重要。
你的 .h 文件应该是这样的:
extern char *keywords[];
然后 一个 .c 文件应该提供定义。
您误解了预处理器的作用,或者 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,因为它们不包含在目标文件中。
请注意:这不是家庭作业。该程序不完整且功能不全,但至少应该可以编译。
我正在使用 C Primer Plus Book 自学(简而言之,我是 C 的新手)。我几乎读完了整本书,并且一直在完成每一章的练习,有时我会跑题。这是那些时代之一。我 运行 遇到了一个特殊问题,我很确定它与预处理器指令有关。
我正在使用 MinGW(windows 的 gcc)并且它报告:
The error that gcc reports is:
nanfunct.c: multiple definition of 'keywords'
nanite.c: first defined here
etc... etc... more errors...
我很确定这是由于包含多个头文件引起的,但更重要的是我创建然后包含的头文件导致了这个问题。
这个问题似乎与指向字符数组(或基于字符串的数组)的指针有关,它们在编译时被复制,尽管我说只有在尚未预定义的情况下才定义它。
例如:
#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
I am using three files:
nanite.c -> source file for main()
nanfunct.c -> source file for functions
nanproto.h -> header file for nanite.c and nanfunct.c
nanite.c 和 nanfunct.c 内部 #include nanproto.h
source files posted on pastebin:
nanproto.h -> Header File for nanite.c and nanfunct.c
nanite.c & nanfunct.c -> source files
为什么会这样?我以为 #ifndef 应该可以防止这样的事情发生?
您将 definitions 放入 .h 文件中是错误的。只有 声明 进入 .h 文件。
如果你把这个(定义):
char * keywords[] = { "foo" };
在一个.h文件中,然后将其包含在多个C文件中,无论您使用哪种#ifdef
ery,您最终都会得到该变量在项目的多个地方定义。
要记住的关键是每个 .c 文件都是独立于其他文件编译的。这意味着,您是否在另一个 C 文件中 #define
d 并不重要。
你的 .h 文件应该是这样的:
extern char *keywords[];
然后 一个 .c 文件应该提供定义。
您误解了预处理器的作用,或者 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,因为它们不包含在目标文件中。