我正在阅读一个文件中同一个标题的多个包含内容,并找到一个有趣的声明(link):
你有意识地使用头文件有几个技巧 多次包括它(这实际上提供了一个有用的 功能)。
据我所知,这些技巧可能在实际项目中不受欢迎和混淆(特别是因为人们会采取预防措施来防范多种内容,例如include guards和#pragma once
)。
但是,那些技巧是什么?我提出了一些想法,但希望看到一些实际的例子(理想情况下,安全和尝试)。
我的想法:
答案 0 :(得分:8)
#include "file"
表示获取头文件并将其所有内容放入#include
行。
我们通常使用标头进行类型定义以及向源文件添加前向声明。在文件中定义两次相同类型(循环包含将始终导致它)会产生编译错误,因此我们使用#ifndef
或#pragma once
。 (或两者兼有)
但是我们也可以放置重复的代码和宏并将其包含几次,即使在同一个文件中也是如此。在这种情况下,我们不会使用#ifndef
或#pragma once
。如果你这样做,你必须格外小心,只有在你知道自己在做什么的情况下才能这样做。
例如:如果在某些操作系统中调用特定的系统功能(或者甚至是ac宏,如:offsetof
)会导致一堆警告,并且它会让您感到困扰,并且您确定你的代码很好,但是你不想禁用你在所有项目或文件上得到的所有警告,你只想在调用特定函数时禁用它。
//suppress the warnings:
#if defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreorder"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wsequence-point"
#endif
#endif // __GNUC__
//here you call the function...
func(x,y,z);
//unsupress: bring back the warnings to normal state
#if defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif // __GNUC__
这将使您的代码看起来非常脏,特别是如果您多次调用该函数。
一种可能的解决方案,(我不是建议它是最好的......)是制作2个标题,一个用于抑制警告,另一个用于取消抑制。
在这种情况下,您的代码可能如下所示:
#include "suppress.h"
func(x,y,z);
#include "unsuppress.h"
//.... more code come here
//now when call it again:
#include "suppress.h"
func(x,y,z);
#include "unsuppress.h"
答案 1 :(得分:2)
&#39;标准&#39;示例是<assert.h>
标头。包含它的效果取决于NDEBUG
:
#include <assert.h>
void func1(void)
{
assert(...);
}
#undef NDEBUG
#include <assert.h>
void func2(void)
{
assert(...);
}
#define NDEBUG
#include <assert.h>
void func3(void)
{
assert(...);
}
func1()
中的断言处于活动状态,除非编译环境中的某些内容在包含NDEBUG
时设置了<assert.h>
。 func2()
中的断言处于活动状态,因为在NDEBUG
被包含时<assert.h>
未定义。 func3()
中的断言处于非活动状态,因为在NDEBUG
被包含时定义了<assert.h>
。
话虽如此,我从未在现实生活中使用过此设施,但C标准祝福(强制执行)所显示的行为。
请注意,这不是偶然发生的;之所以发生这种情况,是因为标题是故意设计成在一个TU中重复使用几次。