【问题标题】:does the static keyword protect variables in #included files?静态关键字是否保护#included 文件中的变量?
【发布时间】:2021-12-29 04:44:47
【问题描述】:

假设我正在编写一个函数库,每个函数都使用一个全局数组来执行其职责。我不想将该数组公开给非库代码,因此我将其声明为static,如下所示:

图书馆.h:

void function1();
void function2();

库.c:

#include "library.h"
static int arr[ARBITRARY_SIZE];
void function1() {...} // both of these
void function2() {...} // make use arr

如果我现在想在我的代码中使用这个库,我会在我的代码顶部使用#include "library.c"

如果我理解正确,#include 只需将#includeed 文件的内容复制并粘贴到位。如果是这种情况,用户代码本身将包含arr 的静态定义。鉴于此,作为库的作者,我将如何保护我的库变量?如果不是这种情况,请纠正我 #include 所做的事情!

【问题讨论】:

  • 您没有将 function1function2 的实际定义放在 .h 文件中(它们放在 .c 文件中),因此您不需要 arr 在.h 也可以。
  • 谢谢,我已经更新了问题。如果实现库函数的任何 .c 文件都包含 .h 并且用户代码包含 .c 文件,那么用户代码不是仍在声明静态变量本身吗?
  • 用户代码包含 .h(不是 .c),因此永远不会看到 arr(但它确实需要与从 .c 生成的 .o 链接)
  • 你没有#include C 文件,只是头文件。
  • 要使用.c 文件中的函数,请链接到相应的.o 文件。

标签: c linker


【解决方案1】:

static 关键字不保护变量使用的内存,您可以从函数(对其可见性)传递出对变量的引用,以便可以从定义它的块中访问该变量。然后调用代码可以根据需要使用该引用来修改它。

static 有两个用途:

  • 在函数体的块内部,它声明:尽管变量仅在定义它的块内部可见,但它的生命是整个程序生命(它不会在程序进入时创建/销毁/存在定义块)
  • 在块之外,它提供本地文件可见性(变量名在定义编译单元之外无处暴露)。但这并不意味着无法访问该全局内存块。如果您有一个指向它的指针引用,您仍然可以根据需要对其进行修改。

#include 只是文本在编译流程中逐字包含包含文件内容,因此在包含文件中声明的所有内容 static 在包含文件中(包含点之后)以及在每个编译单元中本地可见还包括头文件。但是它的所有定义都是不同且独立的,并且它们不引用相同的变量(因为它们是不同编译单元中的局部定义),因为如果您命名不同块的两个局部变量(即使嵌套块时)也会发生这种情况) 同名,它们是不同的变量。

【讨论】:

    【解决方案2】:

    如果我现在想在我的代码中使用这个库,我会在我的代码顶部使用#include "library.c"

    仅当您在单个源文件中使用此库时才有效。

    只要您添加 foo.cbar.c 这两个 #include "library.c" 并尝试将它们链接在一起,您就会得到一个多重定义的 function1function2 符号错误(因为每个 foo.obar.o 现在将提供它们自己的单独定义。

    也可以通过将函数设为静态来解决此问题:static void function1() { ... } 等,但这不是人们通常使用库的方式,因为该方法会导致长时间编译次和大于必要的可执行文件。此外,如果您使用这种方法,您根本不需要library.h 文件

    相反,人们通常所做的是将library.c编译成源文件顶部的library.o#include "library.h",然后将所有内容链接在一起。

    我不想将该数组暴露给非库代码,所以我将它声明为静态,如下所示:

    是一件有效的事情,并且达到了你的目的(只要你是#include "library.h"而不是library.c)。

    请注意,使用全局数组(以及大多数其他全局变量)会使代码更难推理,并在使代码线程安全时造成额外的困难,因此最好谨慎使用全局变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-04
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      相关资源
      最近更新 更多