条件编译的混乱和失败
Conditional compilation confusion and failure
我想用一个通用的*.c文件编译不同的文件。就像我想编译 A.c common.c
xor B.c common.c
但我不知道如何实现。
你能告诉我如何让 common.c 使用不同的 headers 而不使用我的文本编辑器每次我想编译时更改 headers 列表
假设我有 3 个文件:A.c、B.c 和 common.c。
A.h 和 B.h 以不同的方式定义枚举 enum {Mon, Tues, Wed...}
。该枚举用于 common.c。所以我不能只做 common.c:
#include "A.h"
#include "B.h"
我想到的是使用预处理器指令:
在common.h
#define A 1
#define B 2
在A.c
#define COMPILE_HEADER A
并在 common.c
#if COMPILE_HEADER == A
#include A.h
#end
这当然行不通,因为编译器没有访问A.c文件来寻找#define COMPILE_HEADER A
所以你能告诉我如何让 common.c 使用不同的 headers 而不使用我的文本编辑器每次我想编译时更改 headers 列表吗?
解释起来很复杂,但我会试一试。
说明
编译器,例如 gcc,获取提供的输入文件,将头文件包含(实际上只是复制粘贴)到 [=17] 中它们各自的位置(#include
指令所在的位置) =] 文件,然后将文件编译为对象 (*.o
) 文件。没有创建可执行文件。 linker 来了,它包含在 gcc 中。它将 *.o
文件和 links 它们放入一个可执行文件中。
问题是,文件是独立编译的,然后 link 在一起。我的意思是,像 int func(int param);
这样的预定义就像对编译器说 "Hey man, don't worry about any usage of func
in the code, the linker will care"。然后编译器只是将这个用法作为外部符号保存在相应的*.o
文件中,当linker在做他的工作时,他首先找到符号定义(函数实现)的位置,然后指向每当调用 func 时。
尝试在头文件中包含函数定义,然后将其包含在同一项目的 2 个或更多文件中(compiled/linked 在一起)。编译器会说没问题,因为代码是正确的并且生成的代码是有效的。然后,linker 将尝试将它 link 到一个可执行文件中,他将不得不决定它应该 link 到哪个版本的同名参数函数。由于大多数开发人员工具并不真正擅长做出正确的选择,他只会对你大喊大叫 "hey man, you gave me two definitions of same function, what to do now?"。这会导致如下错误:
obj\Release\b.o:b.cpp:(.text+0x0): multiple definition of 'func(int)'
obj\Release\a.o:a.cpp:(.text+0xc): first defined here
在一个项目中有两个 main
怎么样?
obj\Release\b.o:b.cpp:(.text.startup+0x0): multiple definition of 'main'
obj\Release\a.o:a.cpp:(.text.startup+0x0): first defined here
两个文件都能编译,但不能link一起编辑。
头文件旨在包含 class 定义和函数预定义,让您只需编写一次,然后在所有要使用它们的文件之间共享。您始终可以分别为每个文件键入 class 定义(只要它们保持相同)并像在 .h 文件中使用它们一样使用它们,这同样适用于函数预定义。
你的问题来了。您只需编译一个文件,而不是只包含一个文件。您可以使用预处理器技巧来做到这一点,但我不推荐作为解决方案,因为它可以更容易地解决(稍后我会告诉您如何解决)。
TL;DR; (实答无解)
您可以#ifdef / #ifndef 这两个文件,然后在另一个*.c
中定义(或不定义)一些值。例如:
A.cpp
#include "t.h"
#ifdef USE_A
int func(int a)
{
return a + 5;
}
#endif
B.cpp
#include "t.h"
#ifndef USE_A
int func(int a)
{
return a * 10;
}
#endif
T.h
#ifndef T_H
#define T_H
//Or comment to use B
#define USE_A
int func(int a);
#endif // T_H
main.cpp
#include <iostream>
#include "t.h"
using namespace std;
int main()
{
cout << func(3);
}
注意 #ifdef
/#ifndef
在 #include
之后 ,因此预处理器知道要编译哪一个。此外,不可能(至少我想不出任何方法)在任何 .c 文件中进行定义,因为它们是单独编译的(如上所述)。您可以使用 -D 开关,但这涉及在环境中扰乱构建配置,如果您想这样做,最好尝试下面介绍的第二种解决方案。
更好的答案
每个版本选择一个文件编译。它几乎不取决于您的需要,但基本上您应该编译 a.cpp 或 b.cpp 而不是使用 g++ main.cpp a.cpp b.cpp
。如果您正在使用像 Visual Studio 或代码块这样的集成环境,配置管理器允许您决定要包含哪个文件。我的意思是,那些 Debug/Release 下拉菜单可以包含您自己的条目,这将自定义您的项目。 Then, switching between the A.cpp and B.cpp is just a question of choosing appropiate option in the always-visible bar in your environment.
如果您想获得有关如何在 Code::Blocks 或 Visual Studio 上管理配置的更详细教程,请在 Whosebug 上创建适当的问题,我们会立即为您解答:)
我想用一个通用的*.c文件编译不同的文件。就像我想编译 A.c common.c
xor B.c common.c
但我不知道如何实现。
你能告诉我如何让 common.c 使用不同的 headers 而不使用我的文本编辑器每次我想编译时更改 headers 列表
假设我有 3 个文件:A.c、B.c 和 common.c。
A.h 和 B.h 以不同的方式定义枚举 enum {Mon, Tues, Wed...}
。该枚举用于 common.c。所以我不能只做 common.c:
#include "A.h"
#include "B.h"
我想到的是使用预处理器指令:
在common.h
#define A 1
#define B 2
在A.c
#define COMPILE_HEADER A
并在 common.c
#if COMPILE_HEADER == A
#include A.h
#end
这当然行不通,因为编译器没有访问A.c文件来寻找#define COMPILE_HEADER A
所以你能告诉我如何让 common.c 使用不同的 headers 而不使用我的文本编辑器每次我想编译时更改 headers 列表吗?
解释起来很复杂,但我会试一试。
说明
编译器,例如 gcc,获取提供的输入文件,将头文件包含(实际上只是复制粘贴)到 [=17] 中它们各自的位置(#include
指令所在的位置) =] 文件,然后将文件编译为对象 (*.o
) 文件。没有创建可执行文件。 linker 来了,它包含在 gcc 中。它将 *.o
文件和 links 它们放入一个可执行文件中。
问题是,文件是独立编译的,然后 link 在一起。我的意思是,像 int func(int param);
这样的预定义就像对编译器说 "Hey man, don't worry about any usage of func
in the code, the linker will care"。然后编译器只是将这个用法作为外部符号保存在相应的*.o
文件中,当linker在做他的工作时,他首先找到符号定义(函数实现)的位置,然后指向每当调用 func 时。
尝试在头文件中包含函数定义,然后将其包含在同一项目的 2 个或更多文件中(compiled/linked 在一起)。编译器会说没问题,因为代码是正确的并且生成的代码是有效的。然后,linker 将尝试将它 link 到一个可执行文件中,他将不得不决定它应该 link 到哪个版本的同名参数函数。由于大多数开发人员工具并不真正擅长做出正确的选择,他只会对你大喊大叫 "hey man, you gave me two definitions of same function, what to do now?"。这会导致如下错误:
obj\Release\b.o:b.cpp:(.text+0x0): multiple definition of 'func(int)'
obj\Release\a.o:a.cpp:(.text+0xc): first defined here
在一个项目中有两个 main
怎么样?
obj\Release\b.o:b.cpp:(.text.startup+0x0): multiple definition of 'main'
obj\Release\a.o:a.cpp:(.text.startup+0x0): first defined here
两个文件都能编译,但不能link一起编辑。
头文件旨在包含 class 定义和函数预定义,让您只需编写一次,然后在所有要使用它们的文件之间共享。您始终可以分别为每个文件键入 class 定义(只要它们保持相同)并像在 .h 文件中使用它们一样使用它们,这同样适用于函数预定义。
你的问题来了。您只需编译一个文件,而不是只包含一个文件。您可以使用预处理器技巧来做到这一点,但我不推荐作为解决方案,因为它可以更容易地解决(稍后我会告诉您如何解决)。
TL;DR; (实答无解)
您可以#ifdef / #ifndef 这两个文件,然后在另一个*.c
中定义(或不定义)一些值。例如:
A.cpp
#include "t.h"
#ifdef USE_A
int func(int a)
{
return a + 5;
}
#endif
B.cpp
#include "t.h"
#ifndef USE_A
int func(int a)
{
return a * 10;
}
#endif
T.h
#ifndef T_H
#define T_H
//Or comment to use B
#define USE_A
int func(int a);
#endif // T_H
main.cpp
#include <iostream>
#include "t.h"
using namespace std;
int main()
{
cout << func(3);
}
注意 #ifdef
/#ifndef
在 #include
之后 ,因此预处理器知道要编译哪一个。此外,不可能(至少我想不出任何方法)在任何 .c 文件中进行定义,因为它们是单独编译的(如上所述)。您可以使用 -D 开关,但这涉及在环境中扰乱构建配置,如果您想这样做,最好尝试下面介绍的第二种解决方案。
更好的答案
每个版本选择一个文件编译。它几乎不取决于您的需要,但基本上您应该编译 a.cpp 或 b.cpp 而不是使用 g++ main.cpp a.cpp b.cpp
。如果您正在使用像 Visual Studio 或代码块这样的集成环境,配置管理器允许您决定要包含哪个文件。我的意思是,那些 Debug/Release 下拉菜单可以包含您自己的条目,这将自定义您的项目。 Then, switching between the A.cpp and B.cpp is just a question of choosing appropiate option in the always-visible bar in your environment.
如果您想获得有关如何在 Code::Blocks 或 Visual Studio 上管理配置的更详细教程,请在 Whosebug 上创建适当的问题,我们会立即为您解答:)