何时在全局变量前使用static关键字?


73

有人可以解释何时应该在头文件中定义的全局变量或常量之前使用static关键字吗?

例如,假设我有一个带有以下内容的头文件:

应该static在前面const吗?有哪些最佳使用方法static


请注意,在C ++中,对所有全局命名空间限定的变量都static隐含了(即static默认情况下)const,尽管我建议static无论如何都对其进行限定,以使意图明确。
abc

另请参阅如何使用extern源文件之间共享变量? 这些问题的答案有解释如何份额值-和的一个关键部分是使用头声明(但限定),它们共享变量。如果没有标题可用于放置声明,则变量定义应为静态。如果确实有标头,则在定义变量的位置(仅是一个源文件)和使用标头的位置(可能有许多源文件)都包含标头。
乔纳森·莱夫勒

Answers:


56

static在文件本地呈现变量通常是一件好事,例如,请参阅Wikipedia条目


16
我认为这与“文件”无关,而与“编译模块”有关。
AraK

1
如果变量不是extern,则无法从C文件外部访问它。那么将其定义为静态有什么意义呢?
亚历克斯

@alex一个很好的问题。默认情况下,全局变量是extern,但是最好还是将其标记为extern。
奥斯丁·萨尔加特

114

您不应在头文件中定义全局变量。您应该在.c源文件中定义它们。

  • 如果全局变量仅在一个.c文件中可见,则应将其声明为静态。

  • 如果要在多个.c文件中使用全局变量,则不应将其声明为静态。相反,您应该在所有需要它的.c文件包含的头文件中将其声明为extern。

例:

  • 例子.h

  • foo.c

  • bar.c


2
我认为您已经错过了重点。这是一个const浮点数,在头文件中定义它为静态const并在每个转换单元中具有不同的副本没有什么错。但是大多数人只会在文字上使用#define。
史蒂夫·杰索普

6
问题是:“有人可以解释在头文件中定义的全局变量或常量之前,应该何时使用static关键字吗?” 由于OP似乎是初学者,所以我只给出了有关在C中定义全局变量的最基本规则。您已经注意到自己-通常无法在头文件中使用全局_const_s来伤害自己(在C中,在C ++中并不是那么简单)。
Tomek Szpakowicz,2009年

毕竟,这只是编译器的执行。毕竟毕竟,这只是人类的意志……
smwikipedia

1
在foo.c中是否需要包含example.h?
哈马

@hammadian在这种情况下没有必要。仍然包括它是一个好主意。它使编译器有机会检测h文件中的声明与c文件中的定义之间的任何差异。
Tomek Szpakowicz

26

是的,使用静态

.c除非需要从其他.c模块引用该对象,否则请始终在文件中使用static 。

切勿在.h文件中使用静态对象,因为每次包含对象时都会创建一个不同的对象。


链接器看不到它们是常量并优化了所有不同的对象?
Trevor Hickey

但是它们不是常量,链接器不要仅仅因为它们具有相同的名称就将它们意外地合并在一起,这一点很重要。链接程序根本没有高级信息,它们仅处理符号,位字符串,空格和引用。常量对链接程序完全不可见,它们只会影响编译期间生成的代码。
DigitalRoss

6
另一种说法是:的全部目的static允许同一名称成为两个不同模块中的两个不同对象。
DigitalRoss

8

头文件的经验法则:

  • 将变量声明为asextern int foo;并将相应的初始化放在单个源文件中,以获取跨翻译单元共享的可修改值
  • 用于static const int foo = 42;获取可以内联的常数

6

静态关键字是用C来限制函数或变量的可见性给它的翻译单元。转换单元是C编译器的最终输入,可从中生成目标文件。

检查此:链接| 翻译单位


5

static 在全局变量之前,表示无法从定义该变量的编译模块外部访问此变量。

例如,假设您要访问另一个模块中的变量:

现在,如果您声明var为静态,则只能从foo.c编译模块所在的模块访问它。

请注意,模块是当前的源文件,加上所有包含的文件。也就是说,您必须分别编译这些文件,然后将它们链接在一起。


-1

匿名名称空间中C ++的正确机制。如果您想要文件的本地内容,则应使用匿名名称空间而不是static修饰符。


我认为此答案措词不当,过于简洁且不合主题(尽管OP并未指定,但问题被标记为C,而不是C ++)。
p4010

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.