【问题标题】:How to "undeclare" a function prototype or hide a function prototype or #uninclude a header如何“取消声明”函数原型或隐藏函数原型或#uninclude 标头
【发布时间】:2013-10-08 00:08:02
【问题描述】:

我想让函数A() 调用B() 作为内联宏,但我不希望B() 对全世界可见。我只希望A() 可见,如果用户不小心使用了B(),我想要编译器错误。

我知道不用内联怎么做:

// a.h
void A(void);

// a.c
#include "b.h"
void A(void) { B(); }

如果我#include "a.h",那么我可以访问A(),但不能访问B()。没关系;这就是我想要的。

现在我想做同样的事情,但通过将B 内联到A 来降低一级调用复杂性,但我想隐藏B

// a.h
#include "b.h"
#define A() B()
#uninclude "b.h"   <----This is bogus, but I want the equivalent.


// main.c
#include "a.h"
A();  <-- ok
B();  <-- undefined function

这适用于低级固件,调用开销确实会产生影响,但我不想仅仅为了提高效率而放弃高级代码管理。在 C++ 中,这是微不足道的,但我正在寻找 cpp 黑客在纯 C 中做到这一点。

(在我的例子中,a 代表一个 HAL,b 代表一个 BSP。HAL 是特定于处理器的,而 BSP 是特定于板(PCB)的)

【问题讨论】:

  • 你知道#undef,对吧?
  • 在我看来,“高级代码管理”和“cpp hacks”是相互排斥的。一般来说,你无法让 C 编译器阻止一个决心忽略内部文档的开发人员;这就是代码审查的目的。
  • @CharlieBurns -- 我知道#undef,但在这种情况下你如何使用它?我不能#undef A
  • @MarkLakata,对不起,我想我误解了你的问题。

标签: c include header-files c-preprocessor


【解决方案1】:

如果b.h 的唯一声明是B 的声明而不是定义,那么您可以在a.h 中执行此操作:

// a.h
static inline void A(void)
{
    #undef _B__H_  //need this if you have more than one of these inline declarations
    #include "b.h"
    B();
}

假设 b.h 看起来像这样:

// b.h
#ifndef _B_H_
#define _B_H_
void B(void);
#endif

那么B的声明只在A范围内。

a.c 中,一定要包含b.h 之前 a.h(或执行#undef _B_H_ 以强制重新加载b.h)。否则,您将收到有关不兼容范围的警告或错误。 (a.h 在本地范围包括 b.h,而 a.c 在文件范围包括 b.h 然后忽略所有剩余的本地范围包括。)

如果b.h 进行额外声明,只要它们在函数体范围内是可接受的,这也将起作用。

【讨论】:

  • 对此有一个警告,我认为,如果b.h 包括(直接或间接)任何系统头文件,那么#include 函数范围内的那些文件是未定义的行为;它们只能包含在文件范围内。如果这些系统头文件首先包含在文件范围内,你就可以了,但确保这可能很棘手。
  • 这不是开箱即用的,因为我在b.h 中还有其他非内联函数,这些函数不能从a.c(文件级别)中包含,而不会给我范围警告。
  • 很遗憾,因为如果b.h 合适,这是最干净的,因为它不玩预处理器游戏并且保持名称空间干净。也许值得单独创建一个 bClean.h 来声明 B。但我希望B 需要问题中未显示的参数或返回值类型。
  • 我找到了一种解决方法,使其成为最佳解决方案并更新了答案。
【解决方案2】:

如果你这样做:

#define B A
#include "b.h"
#undef B

这会将“b.h”中B 的定义更改为A 的定义。这要求b.h 定义B,而不仅仅是声明它,所以这可能不是你想要的。

然后,在出现这些行的文件中,代码可以使用A(使用诸如A() 之类的调用),但B 的声明不在范围内。所以尝试使用B 会导致编译器错误。 (b.h 中的其他声明将在范围内。)

【讨论】:

  • 这种方法适用于有限的情况,但我在Bspace 中还有其他功能,我不想自动重命名为Aspace。我希望 a.h 决定内联的内容。我仍然会 +1,因为它可能在其他情况下有用。
【解决方案3】:
#define A() (B)()
#define B() syntax error

B() 的人会收到报告的语法错误(以某种形式或形式)。 写A() 的人会产生对(B)() 的调用,这没关系。

当然,这不会阻止有人在代码中写 (B)(),但它已经完成了 80%。

【讨论】:

  • 巧妙的把戏。对我来说这是 99% 的路......有人也可以使用 #include "b.h" 来解决这个问题,所以如果他们正在使用 (B)() 来解决它,他们只是在恶意。
  • 这会产生一个问题/功能。就我而言,这是一个功能。对其他人来说可能是个问题。您现在不能在 b.c 中包含 a.h。这会强制执行a 依赖于b,但b 不依赖于a 的引用树。
  • 有办法解决这个问题;这取决于您是否要使用它们。一种方法是让b.c 中的代码定义一些东西,这意味着a.h 不会重新定义。
猜你喜欢
  • 1970-01-01
  • 2011-08-07
  • 1970-01-01
  • 2012-07-15
  • 2021-03-17
  • 1970-01-01
  • 2014-05-08
  • 1970-01-01
  • 2011-12-16
相关资源
最近更新 更多