更安全的条件编译?

发布于 2024-10-18 06:13:33 字数 576 浏览 1 评论 0原文

在 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

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

In an MSVC C++ program I have a part of code which I want to enable or disable depending on a preprocessor definition

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

But I find that it is quite dangerous when it is used in a .h file included in more than one compilation unit, as I can easily get inconsistent headers (I don't want to define MYOPTION globally as it would require a complete recompilation each time I change it):

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

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

Of course, it is much more complicated than this simplified example due to the chained header inclusion.

Is there a way to avoid such inconsistency, e.g. have a compile-time error without too much effort?

I thought of doing #define MYOPTION 0 or 1, but then I would have to write something like

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

which looks too complicated... Maybe there is a better option?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏尔 2024-10-25 06:13:33

像这样的事情怎么样:让 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)

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

How about something like this: have 1.h define a dummy section in the obj with different options. This way, if MYOPTION is ever used inconsistently, the linker will issue a warning.

1.h:

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

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

Compiling with MYOPTION defined in a.cpp but not in b.cpp yields this linker warning (using VC 2008):

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

A consistent definition yields no linker warnings at all.

小猫一只 2024-10-25 06:13:33

我认为您基本上已经自己列出了大多数解决方案。我会使用最后一个解决方案,但形式可能略有不同:

#ifndef MYOPTION
#error ...
#endif

...

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

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

你说它“看起来太复杂”,但恐怕没有比这更“复杂”的解决方案了。

I think you've listed most solution yourself, basically. I would use the last solution, but perhaps in a slightly different form:

#ifndef MYOPTION
#error ...
#endif

...

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

Because often this #if MYOPTION == 1 will appear more than once in each file. It's also clearer that MYOPTION is a requisite for that file.

You say it "looks too complicated", but I'm afraid there's probably no solution that's less "complicated" than this.

过去的过去 2024-10-25 06:13:33

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

Assuming that you actually need to use the defines, better is to define them via the compiler command line than #define in your source files. Then your configure script/makefile/build process sets the define once and you're guaranteed that it will agree properly across all source files.

陌伤浅笑 2024-10-25 06:13:33

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

您可以转到构建->配置管理器并创建新配置(与调试、发布分开)。创建新配置将允许您定义特定于该配置的预处理器符号。

例如,对于标题为“MyOption 1”的新配置,您可以添加预处理器定义 MYOPTION = 1。同样的情况也适用于 MYOPTION = 2, 3, ...

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

Perhaps what you want is to create a separate configuration.

You can go to Build -> Configuration Manager and create a new configuration (separate from DEBUG, RELEASE). Creating a new configuration will allow you to define preprocessor symbols specific to that configuration.

For example, with a new configuration titled "MyOption 1" you could add the preprocessor definition MYOPTION = 1. The same thing goes with MYOPTION = 2, 3, ...

Each configuration has to be built separately.
DEBUG and RELEASE are examples of separate configurations; DEBUG defines _DEBUG and RELEASE defines NDEBUG

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文