更安全的条件编译?

时间:2011-02-18 20:23:11

标签: c++ visual-studio visual-c++ c-preprocessor

在MSVC C ++程序中,我有一部分代码要根据预处理器定义启用或禁用

// 1.h
#ifdef MYOPTION
//...
#endif

但我发现在多个编译单元中包含的.h文件中使用它是非常危险的,因为我很容易得到不一致的标题(我不想全局定义MYOPTION,因为它需要一个每次我改变时完成重新编译):

// 1.cpp
#define MYOPTION
#include "1.h"

// 2.cpp
#include "1.h"

当然,由于链接头包含,它比这个简化的例子要复杂得多。

有没有办法避免这种不一致,例如有没有太多努力的编译时错误?

我想过做#define MYOPTION 01,但后来我必须写一些像

#if MYOPTION == 1
//...
#elif !defined(MYOPTION)
#error ...
#endif

看起来太复杂......也许有更好的选择?

4 个答案:

答案 0 :(得分:2)

这样的事情:让1.h在obj中用不同的选项定义一个虚拟部分。这样,如果MYOPTION的使用不一致,链接器将发出警告。

1.H:

#ifdef MYOPTION
#pragma section("MYOPTION_GUARD",write)
#else
#pragma section("MYOPTION_GUARD",read)
#endif

namespace { __declspec(allocate("MYOPTION_GUARD")) int MYOPTION_guard; }

使用a.cpp中定义但未在b.cpp中定义的MYOPTION进行编译会产生此链接器警告(使用VC 2008):

b.obj : warning LNK4078: multiple 'MYOPTION_GUARD' sections found with different attributes (40300040)

一致的定义根本不会产生链接器警告。

答案 1 :(得分:1)

我认为你自己已经列出了大多数解决方案。我会使用最后的解决方案,但可能会略有不同:

#ifndef MYOPTION
#error ...
#endif

...

#if MYOPTION == 1
//...
#endif

因为#if MYOPTION == 1通常会在每个文件中出现多次。同样更清楚的是,MYOPTION是该文件的必备条件。

你说它“看起来太复杂了”,但我担心可能没有比这更“复杂”的解决方案。

答案 2 :(得分:0)

假设您确实需要使用定义,最好是通过编译器命令行定义它们,而不是源文件中的#define。然后你的configure脚本/ makefile / build进程设置一次定义,你保证它会在所有源文件中正确地达成一致。

答案 3 :(得分:0)

也许你想要的是创建一个单独的配置。

您可以转到构建 - > Configuration Manager 并创建一个新配置(与DEBUG,RELEASE分开)。创建新配置将允许您定义特定于该配置的预处理程序符号。

例如,使用名为“MyOption 1”的新配置,您可以添加预处理器定义MYOPTION = 1。同样的事情伴随着MYOPTION = 2,3,......

每个配置都必须单独构建。 DEBUG和RELEASE是单独配置的示例; DEBUG定义_DEBUG,RELEASE定义NDEBUG