【问题标题】:How to stop the inclusion of file imported in a file , the file in which the latter has been included in C如何停止包含文件中导入的文件,后者已包含在C中的文件中
【发布时间】:2021-08-20 13:39:58
【问题描述】:

好像 a.c 有代码

#include "b.h"

b.h 有:

#include "c.h"

c.h 有:

void fun()
{

}

在这里我想限制 a.c 访问乐趣,但我希望 b.h 访问 c.h

【问题讨论】:

  • 查找“包括警卫”。而且,避免将函数定义放在头文件中。标头应该只包含声明,而不是定义。例如,void fun(void);
  • 此外,尽管您可以避免b.h 提供fun() 的声明或定义,但如果a.c 中的代码在程序中的某个位置定义了该函数,则不会阻止它调用该函数。

标签: c include


【解决方案1】:

如果文件A.c 包含文件B.h,并且文件B.h 包含文件C.h,并且文件C.h 包含函数func - 那么A 可以调用func - 就是这样该语言有效。


您可以改为C.h 的导入移动到B.c - 包含在A.c 中 - 从而防止在A.c 中包含func。但是你必须将B 分成.h.c - 并显式编译B.c


正如 John 在 cmets 中指出的那样,您应该为每个 .h 文件添加包含保护,例如:

#ifndef _B_H_
#define _B_H_

...

#endif

这可以防止重新包含函数声明。此外 - 在您的 .h 文件中实现函数(例如 int func() { })是不好的做法 - 您应该只包含它们的定义(例如 int func();)并将它们的实现移动到单独的 .c 文件中。

【讨论】:

  • 是的,您可以在 OP 的非常简单的示例中做到这一点,但这种方法在许多实际案例中与最佳实践背道而驰,并且在其中一些案例中完全不可行。 OP 所要求的正是传统的包含守卫提供的内容。
  • @JohnBollinger 包含防护对 OP 的情况没有帮助 - 即使您将包含防护添加到所有 .h 文件,c.h 中定义的 func 仍将在 a.c 中可用.我的建议是在实际案例中发现的 - 不要直接在 .h 文件中使用函数,而是在 .c 文件中使用函数。
  • 除非你和我的包含警卫的意思不同?我指的是例如#ifndef _B_H_b.h 的守卫
  • 我认为问题在于问题很糟糕。我是按照标题来解读的,你好像是按照正文最后一句话解读的。无论如何,OP 都缺乏概念基础。以目前的形式,这个问题最好没有答案,但如果你编辑这个答案,我会举起我的 DV(DV 太旧了,我不能举起它)。
  • 好的,重读标题后,我可以理解其中的困惑——我觉得这有点荒谬,所以我只解决了问题主体:)。将用更多细节编辑我的答案。
【解决方案2】:

首先,这...

在这里我想限制交流访问乐趣

... 与头文件或#include 无关。如果fun 被定义为程序中任何位置的外部函数,则可以从程序中的任何其他位置调用它,尽管有标题。这只是一个知道函数名称的问题,至少知道它的签名。有了这些信息,任何源文件都可以提供自己兼容的函数声明以启用调用(一些编译器甚至可能接受没有声明的调用)。

如果您想限制可以调用fun() 的位置(直接,按名称),则将其声明为static,并将其定义移动到您希望它所在的(唯一)C 源文件中可调用。

至于……

如何停止包含文件中导入的文件,该文件在 后者已被包含在 C

... 严格来说,你不能那样做。如果a.c 包含一个正在处理的#include "b.h" 指令,并且在处理该指令的上下文中,b.h 包含一个正在处理的#include "c.h" 指令,那么效果就是在@ 中包含c.h 的内容987654330@。期间。

如果b.h 包含一个#include 指令,您希望避免在某些情况下被处理,那么条件编译指令(#if#ifdef#ifndef)就是这样做的方法。 “包含守卫”是一个特别常见的例子,根据风格和惯例,每个标题都应该通过适当的包含守卫来保护它的主体。如果您的c.h 这样做了,那么它将解决您从a.c 直接获得的重复函数定义错误,包括b.hc.h

c.h

#ifndef C_H
#define C_H

// everything else ...

#endif

当然,b.h 也应该有自己的包含守卫。

但更重要的是,首先要避免将函数或变量定义放在头文件中。仅将声明放入头文件(并提供原型):

void f(void);

实际定义属于常规源文件 (.c),常规源文件绝不应被任何其他文件为 #included。这是在翻译单元之间共享外部函数和对象的声明而不需要重复定义的方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多