静态声明m遵循非静态声明
我正在尝试一个小例子来了解静态外部变量及其用途。 静态变量属于局部范围,外部变量属于全局范围。
static5.c
#include #include "static5.h" static int m = 25; int main(){ func(10); return 0; }
static5.h
#include 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
EDITED
正确的程序:
ac: #include #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("\ni : %d \n",i); }
这很好用。 但是这被编译成一个单独的编译单元。 因此能够访问静态变量。 在编译单元中,我们不能通过使用extern变量来使用静态变量。
记住这一点(引用Eli Bendersky):
- 函数内的静态变量在调用之间保持其值。
- 静态全局变量或函数仅在其声明的文件中“看到”
在你的代码中, static int m = 25;
表示m
的范围仅限于该文件 ,也就是说,它只在static5.c
可见,而在其他地方不可见。
如果你想在static5.c
之外使用m
, static5.c
确保从变量声明中删除关键字static
。
有关更典型的解释以及示例,请参阅Eli Bendersky的回答
编辑:(根据Klas的建议) **实际范围是编译单元,而不是源文件。 编译单元是文件在预处理器步骤之后的样子
static
有一个非常简单的逻辑。 如果变量是static
,则意味着它是一个全局变量,但它的范围仅限于定义它的位置(即仅在那里可见)。 例如:
- 函数外部:全局变量,但仅在文件中可见(实际上,编译单元)
- 函数内部:全局变量,但仅在函数内可见
- (C ++)一个类:全局变量,但只对类可见
现在让我们看看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;
即static
声明前的extern
声明。 gcc非常好,可以在这种未定义行为的情况下给你错误。
问题完全如错误消息中所述。 m
被声明为普通的int
但后来被定义为static int
。
extern
告诉编译器/链接器在全局变量表中查找变量。
static
(在functon之外)告诉编译器从全局变量表中排除变量。
你看到了冲突吗?
要解决此问题,请从定义中删除static
关键字,或将定义移到包含static5.h
。
应该注意的是,您设计文件的方式不是最佳做法。 包含文件通常不包含函数。
在声明m时删除关键字static,错误将被删除,您将能够得到答案为50. static关键字使范围限制在文件中。