带有警卫的多重头部

时间:2017-12-08 01:37:31

标签: c c-preprocessor c11

假设我有一个特殊的头文件,它被设计为包含多次,并根据某些宏的值生成不同的代码,在包含它之前必须定义它。例如,以下文件dumb.h

#define RETFUNC return_ ## VALUE
static inline int RETFUNC() {
  return VALUE;
}

您可以将其包括在内:

#define VALUE 100
#include "dumb.h"
#define VALUE 200
#include "dumb.h"

它会生成两个版本的函数,如:

static inline return_100 {
  return 100;
}

static inline return_200 {
  return 200;
}

1

如何为这种类型的文件制作标题保护?如果没有警卫,如果头文件的两个不同使用者都请求相同的VALUE,则会出现错误,因为将生成两个相同版本的return_*函数。

现在是一个普通的标题守卫,如:

#ifndef DUMB_H_
#define DUMB_H_
...
#endif // DUMB_H_

不会起作用,因为它只会有效地包含一次文件(上面的#include序列会生成函数的_100版本,但不会生成_200版本)

原则上我想使用令牌粘贴生成宏的名称,以检查作为守卫,如:

#ifndef DUMB_H_ ## VALUE
#define DUMB_H_ ## VALUE
...

但令牌粘贴不能像那样使用(在宏扩展之外)。

是否有任何其他选项可以防止此文件被多次包含在同一VALUE中,但是仍然允许为每个请求的VALUE个人有效地包含该文件一次?

1 不是伟大的,因为这是一个好的模式或类似的东西,但在其中它至少看起来有效。

1 个答案:

答案 0 :(得分:0)

根据comment 1comment 2中的解释,我认为正常过程更像是这样。我将使用一个类型作为参数,并为不同类型生成一个“最小”函数:

dumb.h

#ifndef DUMB_H_INCLUDED
#define DUMB_H_INCLUDED

#define MIN_TYPE(x) \
    static inline x min_ ## x(x v1, x v2) { return (v1 < v2) ? v1 : v2; }

#endif /* DUMB_H_INCLUDED */

消费者代码

#include "dumb.h"
#include <inttypes.h>

MIN_TYPE(int)          // No semicolon; no empty declaration!
MIN_TYPE(double)
MIN_TYPE(uint64_t)

void write_minima(int i1, int i2, double d1, double d2, uint64_t u1, uint64_t u2)
{
    printf("Minima: (%d, %g, %" PRIu64 ")\n",
           min_int(i1, i2), min_double(d1, d2), min_uint64_t(u1, u2));
}

这并不会阻止您尝试在单个TU(转换单元)中两次实例化相同的函数,但如果您这样做,编译器将会反对。坦率地说,让编译器做抱怨比尝试使C预处理器点你搞错并纠正错误更简单。

如果C代码将由另一个程序生成,那么您需要确保代码生成器跟踪它所请求的内容并确保它不会双重生成代码。