我正在尝试一个小例子来了解静态外部变量及其用途.静态变量属于局部范围,外部变量属于全局范围.
static5.c
#include<stdio.h>
#include "static5.h"
static int m = 25;
int main(){
func(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
static5.h
#include<stdio.h>
int func(val){
extern int m;
m = m + val;
printf("\n value is : %d \n",m);
}
Run Code Online (Sandbox Code Playgroud)
gcc static5.c static5.h
o/p:
static5.c:3: error: static declaration of m follows non-static declaration
static5.h:3: note: previous declaration of m was here
Run Code Online (Sandbox Code Playgroud)
EDITED
正确的程序:
a.c:
#include<stdio.h>
#include "a1_1.h"
int main(){
func(20);
return 0;
}
a1.h:
static int i = 20;
a1_1.h:
#include "a1.h"
int func(val){
extern int i;
i = i + val;
printf("\n i : %d \n",i);
}
Run Code Online (Sandbox Code Playgroud)
这很好用.但是这被编译成一个单独的编译单元.因此能够访问静态变量.在编译单元中,我们不能通过使用extern变量来使用静态变量.
Sha*_*baz 17
static有一个非常简单的逻辑.如果变量是static,则表示它是一个全局变量,但它的范围仅限于定义它的位置(即仅在那里可见).例如:
现在让我们看看C11标准所说的static和extern(强调我的):
6.2.2.3
如果对象或函数的文件范围标识符的声明包含存储类说明符
static,则标识符具有内部链接.6.2.2.4
对于使用
extern范围内的存储类说明符声明的标识符,其中该标识符的先前声明是可见的,如果先前声明指定内部或外部链接,则后面声明中的标识符的链接与指定的链接相同在先前的声明.如果没有先前声明可见,或者先前声明未指定链接,则标识符具有外部链接.6.2.2.7
如果在翻译单元内,同一标识符同时出现内部和外部链接,则行为未定义.
所以标准说首先,如果你有:
static int m;
extern int m;
Run Code Online (Sandbox Code Playgroud)
然后第二个声明(with extern)将考虑第一个,最后m仍然是static.
但是,在任何其他情况下,如果存在具有内部和外部链接的声明,则行为未定义.这实际上只留下了一个选项:
extern int m;
static int m;
Run Code Online (Sandbox Code Playgroud)
即extern宣布前的static声明.gcc非常好,在这种未定义行为的情况下会给你错误.
Nli*_*tis 16
记住这一点(引用Eli Bendersky):
- 函数内的静态变量在调用之间保持其值.
- 静态全局变量或函数仅在其声明的文件中"看到"
在你的代码,static int m = 25;意味着m的范围仅限于该文件,也就是说,它是唯一可见的内部static5.c和其他地方.
如果您想使用m外部,请static5.c确保static从变量的声明中删除关键字.
有关更典型的解释,以及示例,请参阅Eli Bendersky的回答
编辑:(根据Klas的建议)**实际范围是编译单元,而不是源文件.编译单元是文件在预处理器步骤之后的样子