我正在尝试一个小例子来了解静态外部变量及其用途。静态变量属于局部范围,外部变量属于全局范围。
static5.c
#include<stdio.h>
#include "static5.h"
static int m = 25;
int main(){
func(10);
return 0;
}
static5.h
#include<stdio.h>
int func(val){
extern int m;
m = m + val;
printf("\n value is : %d \n",m);
}
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
已编辑
正确的计划:
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);
}
这很好用。但是这被编译成一个单独的编译单元。因此能够访问静态变量。在编译单元中,我们不能通过使用extern变量来使用静态变量。
答案 0 :(得分:16)
记住这一点(引用Eli Bendersky):
- 函数内部的静态变量保持其值 调用。
- 静态全局变量或函数仅在“看到”中 它在
中声明的文件
在您的代码中,static int m = 25;
表示m
的范围仅限于该文件,也就是说,它仅在static5.c
内可见且无处可去。
如果您想在m
之外使用static5.c
,请务必从变量声明中删除关键字static
。
有关更典型的解释以及示例,请参阅this answer by Eli Bendersky
编辑:(根据Klas的推荐) **实际范围是编译单元,而不是源文件。 编译单元是文件在预处理器步骤
之后的样子答案 1 :(得分:16)
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;
然后第二个声明(使用extern
)会认为第一个声明m
仍然是static
。
但是,在任何其他情况下,如果存在具有内部和外部链接的声明,则行为未定义。这实际上只留下了一个选项:
extern int m;
static int m;
即extern
声明之前的static
声明。 gcc足以让你在未定义的行为的情况下给你错误。
答案 2 :(得分:3)
问题与错误消息中的说明完全相同。 m
被宣布为正常int
,但后来被定义为static int
。
extern
告诉编译器/链接器在全局变量表中查找变量。
static
(在功能之外)告诉编译器从全局变量表中排除变量。
你看到了冲突吗?
要解决此问题,请从定义中移除static
关键字,或将定义移至包含static5.h
的上方。
应该注意的是,您设计文件的方式不是最佳做法。包含文件通常不包含函数。
答案 3 :(得分:2)
在声明m时删除关键字static,错误将被删除,您将能够得到50的答案.static关键字使范围限制在文件中。