为什么以及何时在C编程中使用静态结构?

kut*_*tty 37 c static struct

我已经被要求修改的驱动程序代码中经常看到静态结构声明.

我试图寻找有关为什么structs声明为静态的信息以及这样做的动机.

你能有人帮我理解这个吗?

fvu*_*fvu 32

staticC中的关键字有几种效果,具体取决于它应用的上下文.

  • 当应用于在函数内声明的变量时,该变量的值将在函数调用之间保留.
  • 当应用于在函数外部声明的变量或函数时,该变量或函数的可见性仅限于它声明的"转换单元" - 即文件本身.对于变量,这归结为一种"局部可见的全局变量".

这两种用法在驱动程序等相对较低级别的代码中非常常见.

前者和后者在应用于变量时,允许函数在调用之间保留状态的概念,这可能非常有用,但是当代码在任何上下文中使用时,这也会导致各种令人讨厌的问题.由多个线程或多个调用者同时使用.如果你不能保证代码将被一个"用户"严格按顺序调用,你可以传递一种在每次调用时由调用者维护的"上下文"结构.

后者应用于函数,允许程序员从模块外部使函数不可见,并且对于某些体系结构的某些编译器可能会更快一些,因为编译器知道它不必使变量/函数在外部可用模块 - 允许函数内联,例如.

  • 对了谢谢.最初的措辞可能会被C语言程序员误解为"哦,静态变量必须谨慎使用,因此它们必须在某种程度上是坏的.我应该避免使用它们,就像gotos和setjmp一样." 它们有其用途,甚至受到编程指南的鼓励,这些指南重视标识符的最小可能链接. (4认同)
  • 慎用?为什么?当您需要具有静态存储持续时间或内部链接的对象时,请使用它们.其他一切都是手工制作. (3认同)
  • @Jens是的,这就是为什么我欢迎这个改进文本的机会. (3认同)

Jen*_*ens 30

显然所有其他答案似乎都错过的东西:staticis并指定对象的存储持续时间,以及自动(局部变量)和分配(malloc和朋友返回的内存).

具有静态存储持续时间的对象在main()启动之前初始化,或者使用指定的初始化程序,或者,如果没有给定,则为0分配给它(对于结构和数组,这适用于每个成员并递归).

static标识符的第二个属性集是其链接,它是链接时使用的概念,并告诉链接器哪些标识符引用同一个对象.所述static关键字使得一个标识符具有内部连接的,这意味着它不能指代相同的名称的标识符在另一翻译单元.

并且对于我之前读过的所有草率的答案都很迂腐:静态变量不能在声明的文件中随处引用.它的范围仅来自其声明(可以在函数定义之间)到源文件的末尾 - 或者甚至更小,到封闭块的末尾.


Cir*_*四事件 14

结构变量

对于像这样的结构变量static struct S s;,这在以下内容中被广泛讨论:"静态"在C中意味着什么?

结构定义:没有效果:

static struct S { int i; int j; };
Run Code Online (Sandbox Code Playgroud)

与以下内容完全相同:

struct S { int i; int j; };
Run Code Online (Sandbox Code Playgroud)

所以永远不要使用它.如果你这样做,GCC 4.8会发出警告.

这是因为结构定义没有存储空间,并且不会在变量和函数等目标文件中生成符号.只是尝试编译和反编译:

struct S { int i; int j; };
int i;
Run Code Online (Sandbox Code Playgroud)

有:

gcc -c main.c
nm main.o
Run Code Online (Sandbox Code Playgroud)

你会看到没有S符号,但有一个i符号.

编译器只是使用定义来计算编译时字段的偏移量.

这是结构定义通常包含在标题中:即使多次包含,它们也不会生成多个单独的数据.

同样的道理enum.

C++ struct definition:C++ 11中不推荐使用

C++ 11 N3337标准草案附件C 7.1.1:

更改:在C++中,静态或外部说明符只能应用于对象或函数的名称使用带有类型声明的这些说明符在C++中是非法的.在C中,在类型声明上使用时会忽略这些说明符.

另见:https://stackoverflow.com/a/31201984/895245


Mih*_*eac 8

如果将变量声明为存在static,则仅在该转换单元中可见(如果是全局声明的)或从调用到调用保留其值(如果在函数内声明).

在你的情况下,我想这是第一种情况.在这种情况下,程序员可能不希望从其他文件中看到该结构.


Bra*_*lor 7

static用于将struct结构的可见范围限制为当前转换单元(即文件)的修饰符.

注意:此答案假定(正如其他响应者已指出)您的声明不在函数内.