问题描述
我刚刚开始学习C编程。
在一些书籍和网络文章中,我发现默认情况下C中的任何全局变量都对应于static
存储类,但具有外部链接。
这是否意味着部分static
和部分extern
?因为据我了解,任何带有static
存储类说明符的全局变量都仅具有内部链接,并且可以在同一文件中进行访问。
P.S:我提到了这个问题Global variables in C are static or not?,但是在C语言中默认情况下,我无法真正得知全局变量是static
还是extern
。
解决方法
无论何时您不想使用在另一个文件中的一个文件中声明的variable
,都应在声明之前使用static
关键字
file1.c:
static int number = 63; // this variable is used only in this file
...
file2.c:
float brightness = 0.5; // is needed in some Other file;
...
file3.c:
extern float brightness; // use external declaration to use it here
...
只要有可能,就应该使用静态变量。
如果要在两个不同的global
(c个文件)中使用两个translation units
变量,则编译器将引发错误,指出该变量已在其他位置声明。
使用static
将使其对其他翻译单元隐藏。
默认情况下,C中的全局变量对应于
static
存储类,但具有外部链接。这是否意味着部分static
和部分extern
?
英语中的“静态”一词在C语言中有多种含义,是的,在函数外部声明的变量的默认值是具有静态存储持续时间和外部链接。
因为这里有多个概念,并且单词含义混合使用,所以我们应该澄清一些术语和格式:
- 使用代码样式来引用源代码中的特定文本,例如关键字
static
。说到静态存储持续时间或外部链接,“静态”和“外部”仅是英语形容词,不应采用代码样式。 - “全局”是指在整个程序中可见。 C标准没有为此目的使用该词。它使用“外部”来指代任何功能之外(外部)的事物。 (但是它也将“外部”用于其他目的。)全局变量不能具有内部链接,因为它在整个程序中都不可见。
- 变量由一个对象(保留用于表示值的内存)和一个标识符(名称)组成。存储持续时间是对象的属性。链接是标识符的属性。
英语单词“ static”通常表示不变。 C标准以多种方式使用此单词和关键字static
:
- 静态存储持续时间意味着在整个程序执行过程中都会保留对象的内存。
- 在声明中使用
static
关键字(如下所述除外),既可以给出对象的静态存储持续时间,又可以在函数外部的声明中给出标识符的内部链接。 - 与
static
一样,在参数声明的下标标记内使用void foo(int a[static 3])
关键字表示该参数至少指向指定数量的元素。 - 使用
_Static_assert
的静态断言提供编译时测试(可以帮助检测错误或确保使用期望的设置来编译程序)。
不幸的是,这些多种用法至少部分是由于C语言的开发历史。
,您混合使用static
和静态存储时间。
存储期限和链接是不同的术语。 C语言中没有什么叫做“全局”的,尽管该术语经常被随意使用在文件作用域中声明的任何变量,即:在任何函数之外。更正确地使用“全局”一词是指变量具有外部链接,这意味着可以在整个项目中的任何地方引用它。
在文件范围内声明的所有变量均具有静态存储期限。这决定了如何初始化此类变量,以及它们在程序的整个执行过程中持续存在(实际上,这也可能意味着变量最终在实现的.data
或.bss
段中结束)。>
在文件范围内声明但没有任何存储类说明符(static
和extern
都没有)的变量具有外部链接,但仍然获得静态存储期限。从6.2.4:
如果对象标识符的声明具有文件范围并且没有存储类说明符,则其链接是外部的。
但是,如果将存储类说明符添加到文件作用域变量中,则可以同时指定 存储持续时间和链接。 6.2.4 / 3:
如果对象或函数的文件作用域标识符的声明包含存储类说明符
static
,则该标识符具有内部链接。
正如您所说,具有内部链接的变量只能从同一文件中引用(严格说来是相同的“ 翻译单元”)。
如果您将static
添加到局部变量,则此处会有一些细微的区别-它随后指定了存储期限,但未指定链接。整个链接的术语相当混乱-简而言之,该术语的目的是规定何时两个具有相同名称的变量引用相同或不同的对象。对于那些制作编译器/链接器以及意大利面条式编程器的人来说,这主要是一个问题。请遵循以下建议,避免属于后一种。
初学者无需担心以上任何一项。 初学者的经验法则:
- 切勿在函数外部声明变量,除非它们是
static
。 - 永远不要在头文件中声明变量。
- 请勿使用
extern
。 - 如果不希望从其他文件中调用函数,请在函数前使用
static
。
这会让您走得更远,而实际上需要在不同文件之间共享变量的罕见情况是另一个故事/高级主题。