18

static 关键字将全局变量的范围限制在该翻译单元内。如果我 static int x在 .h 文件中使用并包含该 .h 文件每隔一个文件,它们不都属于同一个翻译单元吗?那么,x 不是随处可见吗?那么静态现在的作用是什么?

另外,有没有使用static const int x, 其中 x 是一个全局变量?默认情况下不是所有的 const 全局变量都是静态的吗?并且 const 变量的范围是否仅限于 TU,即使它限制在文件中的 for 循环中?

4

6 回答 6

49

如果你写

static const int x

.h文件中, #include -s this .h的每个翻译单元都有自己的私有变量x

如果你想让每个人都能看到 1 个全局变量,你应该写

extern const int x;

.h文件中和

const int x = ...;

.cpp文件之一中。

如果您想让一个静态 const int 仅对一个翻译单元可见 - 根本不要在.h文件中提及它。

于 2012-08-15T10:20:05.437 回答
7

如果我在 .h 文件中使用 static int x 并在每个其他文件中包含该 .h 文件,它们不都属于同一个翻译单元吗?

如果您将某些内容声明为静态(不在类内部,因为 class static 关键字具有不同的语义),则在其 TU 之外无法看到该静态变量。因此,将它放在头文件中将导致包括该头文件的每个 TU 拥有该静态变量的不同私有副本。

并且 const 变量的范围是否仅限于 TU,即使它限制在文件中的 for 循环中?

不。即使对于静态 const 值,范围也由它的声明决定。因此,范围将受到您的 for 括号的限制。

于 2012-08-15T10:17:58.493 回答
3

你最终会得到每个翻译的那个变量的私有副本,如果你把它放在那里会导致膨胀。必须在整个地方随机复制也是没有意义的。不,不行。

你可以const int在一个namespace块中声明一个;没关系。

于 2012-08-15T10:15:53.327 回答
2

const可观察到的合格变量的区别在于,在该static版本中,每个翻译单元将获得一份副本,因此两个此类副本的地址比较可能会失败。

如果您从不使用const变量的地址,任何现代编译器都应该能够只使用该值并优化变量本身。在这种情况下,一个static const-qualified 变量是完全可以的。

于 2012-08-15T10:35:50.597 回答
1

基本上,每个源文件连同所有包含的头文件都是一个翻译单元。因此,如果您在头文件中有一个静态变量,那么它在包含头文件的每个源文件(翻译单元)中都是唯一的。

于 2012-08-15T10:16:21.977 回答
0

“静态全局”没有意义,它们在某种程度上是相互对立的。

术语“全局”经常被误用来描述在文件范围内的任何函数之外声明的变量。相反,全局变量是具有外部链接的变量,可以由项目中的任何文件访问 - 因此是全局变量。

与外部链接相反的是内部链接,这意味着变量只能由声明它的翻译单元访问。翻译单元意味着一个.c文件及其包含的所有标题(递归)。

static是变量获得内部链接的保证。因此其他翻译将无法访问它或声明extern引用它的变量。

如果您static在头文件中声明一个变量会发生什么情况,多个翻译单元将获得一个具有该名称的单独变量。尽管聪明的链接器会注意到这一点并给出链接器错误,但代码会编译得很好。这些类型的链接器错误通常是非描述性的并且难以追踪。

这导致我们采用以下最佳实践:

  • 永远不要在头文件中声明任何变量,因为这通常会产生细微的错误和链接器错误。
  • 为防止出现此类错误,请始终使用“header guards”包围所有头文件:

    #ifndef MYHEADER_H 
    #define MYHEADER_H 
      /* contents of header */ 
    #endif
    
  • static出于私有封装和减少命名空间混乱的目的,应声明在文件范围内声明的所有变量。同样,extern应该避免,因为它会导致糟糕的设计和意大利面条式编程。

于 2018-09-26T07:06:08.030 回答